使用Entity Framework Core调用存储过程遇SqlNullValueException如何处理?
解决.NET 9中调用存储过程返回NULL值时抛出SqlNullValueException的问题
问题根源
这个异常不是因为存储过程返回空列表,而是存储过程返回的结果集中存在NULL值,但对应的VystupyOdkazyModel实体属性是不可空的值类型(如int、DateTime等),EF Core在将数据库NULL值映射到不可空值类型属性时会抛出SqlNullValueException。
解决步骤
1. 修正实体模型的可空属性
检查VystupyOdkazyModel类的所有属性,找到与存储过程返回字段对应、但可能为NULL的属性,将其改为可空类型:
// 示例:将不可空的int改为可空int? public int? SomeNullableField { get; set; } // 将不可空的DateTime改为可空DateTime? public DateTime? SomeNullableDate { get; set; }
确保所有可能返回NULL的数据库字段,都对应实体中的可空属性。
2. 安全传递存储过程参数(避免SQL注入)
你当前使用字符串插值传递参数存在SQL注入风险,同时可能导致可空参数处理异常,改用SqlParameter传递参数:
public async Task<List<VystupyOdkazyModel>> GetOdkazyAsync(int projekt, short typK, DateTime dateFrom, DateTime dateTo, int CurrProgram, int? misto) { var parameters = new[] { new SqlParameter("@projekt", projekt), new SqlParameter("@typK", typK), new SqlParameter("@from", dateFrom), new SqlParameter("@to", dateTo), new SqlParameter("@program", CurrProgram), // 处理可空参数:如果misto为null,传入DBNull.Value new SqlParameter("@misto", misto.HasValue ? (object)misto.Value : DBNull.Value) }; // 使用FromSqlRaw执行存储过程 var result = await _db.VystupyOdkazy.FromSqlRaw( "EXECUTE dbo.sp_GetSumareOdkazu @projekt, @typK, @from, @to, @program, @misto", parameters ).ToListAsync(); // 空列表直接返回,无需额外判断(ToListAsync返回空列表而非null) return result ?? new List<VystupyOdkazyModel>(); }
3. 正确处理异常捕获
你当前的try-catch块直接throw,等于没有处理异常。如果需要捕获并处理该异常,可以在GetOdkazyAsync内部添加捕获逻辑,或者在调用处处理:
try { Odkazy = await GetOdkazyAsync(projekt, typK, dateFrom, dateTo, (int)CurrProgram, misto); } catch (SqlNullValueException ex) { // 处理NULL映射异常,比如返回空列表或记录日志 Odkazy = new List<VystupyOdkazyModel>(); // 可选:记录日志 // _logger.LogError(ex, "存储过程返回NULL值导致映射失败"); } catch (Exception ex) { // 处理其他异常 // _logger.LogError(ex, "调用存储过程时发生错误"); throw; }
额外说明
ToListAsync在没有数据时会返回空列表而非null,所以你原来的if (result != null)判断是多余的,可以直接返回result。- 确保存储过程返回的结果集字段名、类型与
VystupyOdkazyModel的属性完全匹配,否则也可能导致映射异常。
内容的提问来源于stack exchange,提问作者Jan Šalomoun
相关产品推荐
相关产品推荐

