Entity Framework Core调用返回标量值存储过程的最优解决方案
EF Core 5.0 调用返回标量值存储过程的最优方案
报错原因修复
你遇到的ExecuteSqlCommandAsync不存在的编译错误,是因为EF Core 3.0+版本已将该方法重命名为ExecuteSqlRawAsync,同时需要在SQL语句中给输出参数加上OUTPUT标识,修正后的代码如下:
SqlParameter orderId = new SqlParameter("@orderid",orderId); SqlParameter customerid = new SqlParameter("@customerid", customerId); SqlParameter isDelivered = new SqlParameter { ParameterName = "@Value", SqlDbType = System.Data.SqlDbType.BigInt, Direction = System.Data.ParameterDirection.Output }; await _dbContext.Database.ExecuteSqlRawAsync("[dbo].[is_delivered] @orderid , @customerid, @Value OUTPUT", orderId , customerid, isDelivered); var result = Convert.ToInt64(isDelivered.Value);
最优通用方案(无实体,不受Scaffold影响)
推荐直接调用DbContext底层的ADO.NET连接执行标量查询,不需要定义任何额外实体,也不会被dbScaffold --force操作覆盖,兼容所有返回标量的存储过程场景:
await using var cmd = _dbContext.Database.GetDbConnection().CreateCommand(); // 存储过程名 cmd.CommandText = "dbo.is_delivered"; cmd.CommandType = System.Data.CommandType.StoredProcedure; // 传入参数 cmd.Parameters.Add(new SqlParameter("@orderid", orderId)); cmd.Parameters.Add(new SqlParameter("@customerid", customerId)); // 打开连接执行查询 await _dbContext.Database.OpenConnectionAsync(); var result = Convert.ToInt64(await cmd.ExecuteScalarAsync());
该方案优势:
- 无额外实体定义成本,不需要在DbContext中注册任何模型
- 完全不受Database First模式下Scaffold操作的影响
- 执行效率更高,省去了实体映射的开销
可选:保留无键实体的兼容方案
如果你希望继续使用原来的ScalarBool无键实体方案,可以把实体配置写到单独的DbContext分部类中,避免被自动生成的代码覆盖:
- 新建和自动生成的DbContext同名的分部类文件,比如
MyDbContext.partial.cs - 在文件中实现
OnModelCreatingPartial方法,写入自定义配置:
public partial class MyDbContext { partial void OnModelCreatingPartial(ModelBuilder modelBuilder) { modelBuilder.Entity<ScalarBool>().HasNoKey(); } }
执行Scaffold操作时只会覆盖自动生成的类文件,不会修改自定义的分部类内容,ScalarBool的配置会永久保留。
内容的提问来源于stack exchange,提问作者rav
相关产品推荐
相关产品推荐

