EF Core .NET7迁移中调用带DateTime参数存储过程无结果问题
EF Core调用存储过程DateTime参数无结果问题排查与修复
问题现象
将EF6项目迁移至.NET7 EF Core后,数据库表创建正常,但调用存储过程tsp_GetDocuments时出现异常:
- 在SSMS中执行存储过程传入
@fromDate能得到预期结果 - 应用中传入
fromDate参数无返回结果,不传该参数则有部分结果
代码错误分析
参数赋值错误
在创建@fromDate参数时,错误地将Value赋值为toDate,导致实际传入存储过程的@fromDate是toDate的值,而非方法参数的fromDate:
// 错误代码 new SqlParameter() { ParameterName = "@fromDate", SqlDbType = System.Data.SqlDbType.DateTime, Direction = ParameterDirection.Input, Value = (object)toDate ?? DBNull.Value // 此处应为fromDate }
FromSqlInterpolated用法错误
使用FromSqlInterpolated时,错误地将SqlParameter对象直接插入到SQL字符串中,还额外给第一个参数加了单引号,这会导致参数传递格式错误,SQL无法正确解析DateTime值:
// 错误代码 FromSqlInterpolated<tsp_GetDocuments_Result>($"EXECUTE [dbo].[tsp_GetDocuments] '{@params[0]}',{@params[1]},{@params[2]},{@params[3]},{@params[4]}")
修正后的代码
public partial class Entities : DbContext { public virtual DbSet<tsp_GetDocuments_Result> tsp_GetDocuments_Result { get; set; } partial void OnModelCreatingPartial(ModelBuilder modelBuilder) { modelBuilder.Entity<tsp_GetDocuments_Result>(entity => entity.HasKey(e => e.IdDocumentHeader)); } public IEnumerable<tsp_GetDocuments_Result> tsp_GetDocuments(DateTime? fromDate, DateTime? toDate, int? warehouseFrom, int? warehouseTo, string documentType) { // 修正参数赋值错误 var fromDateParam = new SqlParameter("@fromDate", SqlDbType.DateTime) { Value = fromDate.HasValue ? (object)fromDate : DBNull.Value }; var toDateParam = new SqlParameter("@toDate", SqlDbType.DateTime) { Value = toDate.HasValue ? (object)toDate : DBNull.Value }; var warehouseFromParam = new SqlParameter("@warehouseFrom", SqlDbType.Int) { Value = warehouseFrom.HasValue ? (object)warehouseFrom : DBNull.Value }; var warehouseToParam = new SqlParameter("@warehouseTo", SqlDbType.Int) { Value = warehouseTo.HasValue ? (object)warehouseTo : DBNull.Value }; var documentTypeParam = new SqlParameter("@documentType", SqlDbType.VarChar, 20) { Value = documentType ?? DBNull.Value }; // 使用FromSqlRaw并传入参数数组,避免插值格式错误 var results = tsp_GetDocuments_Result .FromSqlRaw("EXECUTE [dbo].[tsp_GetDocuments] @fromDate, @toDate, @warehouseFrom, @warehouseTo, @documentType", fromDateParam, toDateParam, warehouseFromParam, warehouseToParam, documentTypeParam) .ToArray(); return results; } }
额外优化建议
- 存储过程的参数如果允许为空,建议在定义时加上
NULL默认值,比如@fromDate DATETIME = NULL,这样调用时可以省略不需要的参数 - 可以使用EF Core的简化写法,直接传递方法参数而非手动创建
SqlParameter,EF会自动处理参数转换:
// 简化写法 public IEnumerable<tsp_GetDocuments_Result> tsp_GetDocuments(DateTime? fromDate, DateTime? toDate, int? warehouseFrom, int? warehouseTo, string documentType) { return tsp_GetDocuments_Result .FromSqlInterpolated($"EXECUTE [dbo].[tsp_GetDocuments] {fromDate}, {toDate}, {warehouseFrom}, {warehouseTo}, {documentType}") .ToArray(); }
内容的提问来源于stack exchange,提问作者Martina
相关产品推荐
相关产品推荐

