在.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




