C#使用OLEDB执行Access查询时cntSOC字段返回值错误问题
问题原因
1. OleDb字段类型推断错误
OleDb驱动默认会扫描查询结果的前8行自动推断每一列的数据类型,你的LabNumber字段以1E开头符合科学计数法数值格式,驱动会错误识别列的类型映射,导致相邻的cntSOC整数字段读取时发生类型转换失败,返回整数的默认值0。
2. 通配符*查询引发字段顺序错位
如果表中存在隐藏字段、计算字段或者历史修改过字段顺序,使用Select *返回的字段顺序可能和你预期不一致,GetValues方法严格按照查询返回的字段顺序填充数组,可能你认为下标为1的位置对应cntSOC,实际对应到了其他值为0的字段。
3. 计算字段兼容性缺陷
如果cntSOC是Access表中定义的计算字段,旧版OleDb驱动(尤其是Jet 4.0驱动)对这类字段的读取支持存在原生缺陷,大概率会返回错误的默认值而非实际计算结果。
解决方法
- 调整连接字符串配置,添加
IMEX=1和MaxScanRows=0参数,强制驱动关闭自动类型推断,将所有列按文本格式读取,示例ACE驱动连接字符串:Provider=Microsoft.ACE.OLEDB.12.0;Data Source=你的数据库文件路径.accdb;Persist Security Info=False;IMEX=1;MaxScanRows=0; - 将查询SQL的通配符替换为显式指定字段名,避免字段顺序错位:
Select LabNumber, cntSOC FROM MADW_CNT_D
- 优化读取逻辑,改为按字段名获取索引读取,替代按位置填充的
GetValues方法,避免顺序错位问题,修改后代码示例:
public static List<object[]> ReadQueryToList(string connectString, string query) { List<object[]> list = new List<object[]>(); using (OleDbConnection con = new OleDbConnection(connectString)) { using (OleDbCommand dbCommand = new OleDbCommand(query, con)) { con.Open(); using (OleDbDataReader oleReader = dbCommand.ExecuteReader()) { // 提前获取字段索引,避免循环内重复查找损耗性能 int labNumberIndex = oleReader.GetOrdinal("LabNumber"); int cntSocIndex = oleReader.GetOrdinal("cntSOC"); while (oleReader.Read()) { object[] arr = new object[2]; arr[0] = oleReader.IsDBNull(labNumberIndex) ? string.Empty : oleReader.GetString(labNumberIndex); arr[1] = oleReader.IsDBNull(cntSocIndex) ? 0 : oleReader.GetInt32(cntSocIndex); list.Add(arr); } } } } return list; }
- 如果
cntSOC确为Access计算字段,建议将计算逻辑迁移到SQL查询中实现,避免依赖Access本地的计算字段逻辑。
内容的提问来源于stack exchange,提问作者Netlab
相关产品推荐
相关产品推荐

