You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在.NET Core 5控制台应用中使用Entity Framework Core调用SQL Server标量值函数失败排查

解决EF Core 5调用SQL Server标量函数的问题

我帮你找出了几个导致代码无法正常运行的关键问题,咱们一步步修正:

1. 空连接字符串

你的OnConfiguring方法里连接字符串是空的,这会导致程序根本连不上SQL Server数据库。必须替换成符合你环境的有效连接字符串,比如本地Windows认证的连接字符串:

optionsBuilder.UseSqlServer("Server=.;Database=testDB;Trusted_Connection=True;");

2. 错误的函数调用方式

你直接调用testDBContext.FuncTest()会执行C#代码里的throw new NotImplementedException(),而不是生成SQL去调用数据库里的标量函数。EF Core 5中调用标量函数有两种常用方式:

方式一:直接执行SQL查询(最直接)

使用Database.SqlQuery<T>扩展方法执行函数调用:

var test = ss.Database.SqlQuery<int>("SELECT dbo.FuncTest()").FirstOrDefault();

方式二:通过LINQ查询使用映射的函数

如果你想通过EF的函数映射来调用,需要确保函数在LINQ查询中使用(EF会自动转换成SQL),比如:

// 这里通过LINQ查询触发函数调用,EF会生成包含FuncTest()的SQL
var test = ss.Persons.Select(_ => testDBContext.FuncTest()).FirstOrDefault();

3. 重复的函数配置

你同时使用了[DbFunction]特性和modelBuilder.HasDbFunction()配置,其实两者选其一即可。可以简化上下文的配置,只保留特性更简洁:

简化后的上下文函数定义:

[DbFunction("FuncTest", "dbo")]
public static int FuncTest()
{
    throw new NotImplementedException(); // 这个只是占位,EF不会执行它
}

修正后的完整C#代码

上下文类(简化配置)

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
#nullable disable
namespace TestConsoleApp.Models
{
    public partial class testDBContext : DbContext
    {
        public testDBContext() { }
        public testDBContext(DbContextOptions<testDBContext> options) : base(options) { }
        public virtual DbSet<Person> Persons { get; set; }

        [DbFunction("FuncTest", "dbo")]
        public static int FuncTest()
        {
            throw new NotImplementedException();
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                // 替换成你的实际连接字符串
                optionsBuilder.UseSqlServer("Server=.;Database=testDB;Trusted_Connection=True;");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.HasAnnotation("Relational:Collation", "Latin1_General_CI_AS");

            modelBuilder.Entity<Person>(entity =>
            {
                entity.HasNoKey();
                entity.Property(e => e.FirstName)
                    .HasMaxLength(255)
                    .IsUnicode(false);
                entity.Property(e => e.LastName)
                    .HasMaxLength(255)
                    .IsUnicode(false);
                entity.Property(e => e.PersonId).HasColumnName("PersonID");
            });

            // 可以移除这行,因为已经有[DbFunction]特性了
            // modelBuilder.HasDbFunction(() => FuncTest()).HasName("FuncTest").HasSchema("dbo");

            OnModelCreatingPartial(modelBuilder);
        }

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
    }
}

主程序调用(方式一示例)

using System;
using TestConsoleApp.Models;
namespace TestConsoleApp
{
    public class Program
    {
        static void Main(string[] args)
        {
            using (var ss = new testDBContext())
            {
                // 直接执行SQL调用标量函数
                var test = ss.Database.SqlQuery<int>("SELECT dbo.FuncTest()").FirstOrDefault();
                Console.WriteLine($"函数返回值:{test}"); // 会输出5
                int test2 = 23;
            }
        }
    }
}

额外注意事项

  • 确保你的SQL Server服务正在运行,并且testDB数据库已经创建完成(包括函数FuncTest
  • EF Core 5的SqlQuery扩展方法需要引用Microsoft.EntityFrameworkCore命名空间,如果你没引用的话需要加上

内容的提问来源于stack exchange,提问作者HelloWorld1

火山引擎 最新活动