如何用ExecuteReader()高效将数据添加至List并解决空值异常
使用ExecuteReader()读取全量数据时遇SqlNullValueException的解决方法
问题场景
- UI中设按钮用于展示表内剩余记录,控制器通过带
LIMIT和OFFSET的SELECT *语句实现需求,用ExecuteReader()读取数据并转换为自定义Run类的List集合 - SSMS中无论
LIMIT设多大都能正常执行,超过表行数时会返回所有行;但WebAPI里LIMIT>200时抛出System.Data.SqlTypes.SqlNullValueException,异常信息为Data is Null. This method or property cannot be called on Null values.,LIMIT<200时则能正常返回Run类型列表 - 怀疑流式读取转
Run类的步骤有问题,不确定是否需要先把所有数据存入List、关闭连接后再转换为Run实例
问题根源
数据库返回的部分字段存在空值,从SqlDataReader读取数据转换到Run类时,直接调用了不允许空值的读取方法(比如reader.GetString()、reader.GetInt32()等),读取到空值时就触发了异常。前200条数据恰好没有空值,所以能正常执行,超过200后读到带空值的记录就抛出了异常。
解决方法
1. 读取数据时增加DbNull检查
读取每个字段前先判断是否为DBNull.Value,再执行赋值逻辑,示例代码:
using (var reader = cmd.ExecuteReader()) { var runs = new List<Run>(); while (reader.Read()) { var run = new Run { Id = reader.IsDBNull(reader.GetOrdinal("Id")) ? null : reader.GetInt32(reader.GetOrdinal("Id")), Name = reader.IsDBNull(reader.GetOrdinal("Name")) ? null : reader.GetString(reader.GetOrdinal("Name")), // 其他字段按此逻辑逐个检查空值 }; runs.Add(run); } return runs; }
2. 确保自定义Run类支持空值
类中的属性需定义为可空类型(比如用int?替代int,string本身支持空值),否则VS会阻止空值赋值操作,示例:
public class Run { public int? Id { get; set; } public string Name { get; set; } // 其他需要支持空值的属性同理定义 }
额外说明
不需要先把所有数据存入中间List再转换,ExecuteReader()流式读取时直接处理空值即可解决问题,核心是处理数据库空值与自定义类属性的兼容性。
内容的提问来源于stack exchange,提问作者BoGoodSki
相关产品推荐
相关产品推荐

