Ingres数据库Adapter.Fill返回错误行数据问题求助
看起来你碰到了Ingres .NET驱动和VDBA客户端查询结果不一致的棘手问题——明明SQL在VDBA里跑是对的,代码里返回的结果却偏移了。我之前处理过类似的Ingres日期查询问题,大概率是日期格式解析差异或者连接配置不匹配导致的,下面给你几个具体的排查和解决步骤:
1. 立刻改用参数化查询(最可能解决问题)
你现在直接把日期字符串硬编码进SQL里,这不仅有SQL注入风险,更关键的是Ingres驱动对字符串日期的解析逻辑和VDBA可能不一样。比如VDBA可能默认识别YYYY-MM-DD HH:MI:SS,但驱动可能因为区域设置或者连接参数,把这个格式解析成了别的,导致你的between条件实际上没生效,返回了不符合预期的结果。
修改你的代码,用参数化方式传递日期值:
// 在MainWindows.xaml.cs中 SQL S = new SQL(); var query = @"select datanl from REDACTED where datanl between @startDate and @endDate and belart = 'A' and planist = 1 order by datanl asc"; var parameters = new List<IngresParameter> { new IngresParameter("@startDate", new DateTime(2023, 1, 4, 0, 0, 0)), new IngresParameter("@endDate", new DateTime(2023, 1, 5, 0, 0, 0)) }; dataTable = S.ExecuteQuery(query, parameters);
这样驱动会直接传递原生的DateTime类型,完全避免字符串解析的歧义,这是解决这类问题的首选方案。
2. 匹配VDBA的连接配置参数
Ingres的连接字符串有几个关键参数会影响日期时间的处理,你需要确保驱动的配置和VDBA一致:
DateFormat:指定日期格式,比如DateFormat=ISO对应标准的YYYY-MM-DDTimeZone:设置会话时区,比如TimeZone=Local或者和VDBA相同的时区DateTimeFormat:控制datetime类型的解析格式
你可以先在VDBA里执行这条SQL查看当前配置:
SELECT DATE_FORMAT, TIME_ZONE FROM II_SYSTEM.IIDBCFG
然后把对应的参数添加到你的连接字符串里,比如:
"Server=xxx;Database=xxx;User ID=xxx;Password=xxx;DateFormat=ISO;DateTimeFormat=ISO;TimeZone=Local"
3. 升级Ingres .NET驱动版本
如果你用的Ingres.Client版本比较旧,很可能存在日期处理的兼容性bug。建议升级到Actian官方发布的最新Ingres .NET驱动版本,新版本通常会修复这类和VDBA客户端不一致的问题。
4. 验证查询的实际执行逻辑
有时候看起来相同的SQL,在驱动和VDBA里的执行逻辑可能有差异,你可以:
- 在代码中打印参数的实际值,确认传递的日期是否正确:
// 在ExecuteQuery方法中添加日志 if (parameters != null) { foreach (var param in parameters) { Console.WriteLine($"参数 {param.ParameterName}: {param.Value}"); } } - 在Ingres数据库中开启查询日志,对比VDBA和代码执行的查询是否完全一致,包括参数值和执行计划。
5. 检查结果集的完整性
你提到结果有偏移,先对比VDBA和代码返回的结果总条数是否一致:
Console.WriteLine($"代码返回的结果条数: {dataTable.Rows.Count}");
如果条数不一致,可能是驱动的FetchSize参数设置有问题,或者存在隐形的分页逻辑。你可以尝试在连接字符串中添加FetchSize=0(表示一次性获取所有结果)。
小提醒:你的第二个查询方法有个bug
你写的PullData方法里,在dataTable.Load(I_RDR)之前调用了while (I_RDR.Read()),这会把DataReader的指针移到结果集的末尾,导致dataTable.Load加载不到任何数据。虽然这不是你当前问题的根源,但还是要修正:
using (IngresDataReader I_RDR = I_CMD.ExecuteReader()) { var dataTable = new DataTable(); dataTable.Load(I_RDR); // 直接加载,不需要提前Read return dataTable; }
内容的提问来源于stack exchange,提问作者Reddi3n

