使用DataTable.Select筛选DateTime列时出现类型不匹配错误的原因
问题分析与解决方案
这个问题的核心在于你用单引号把日期字符串括起来了,在DataTable的Select筛选语法里,单引号是用来包裹字符串的,所以当你把DateTime对象拼接成字符串并用单引号括起来时,筛选器会把它当作字符串类型处理,而你的Datum列是DateTime类型,自然就会出现“字符串和DateTime无法比较”的错误。
那为什么第一条语句没报错呢?其实这只是个巧合——某些情况下,.NET会尝试隐式转换字符串到DateTime,但这种转换依赖于系统的区域设置,非常不可靠,第二条语句刚好触发了转换失败的情况而已,本质上两条语句的写法都是不规范的。
正确写法1:使用标准日期语法(#包裹)
要解决这个问题,你需要用**#符号**来包裹日期值(这是OleDb筛选语法中表示日期的标准方式),同时最好显式指定日期的格式化字符串,避免区域设置带来的问题:
// 计算当月第一天和最后一天 var firstDayOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1); var lastDayOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month)); // 使用#包裹日期,并且格式化为ISO格式 DataRow[] foundRows = dt.Select($"Datum >= #{firstDayOfMonth:yyyy-MM-dd}# AND Datum <= #{lastDayOfMonth:yyyy-MM-dd}#");
正确写法2:使用Linq筛选(更安全)
另外还有一种更稳妥的方式——避免字符串拼接,直接用Linq来筛选DataTable,这样类型更安全,也不会有语法格式的问题:
var firstDayOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1); var lastDayOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month)); var foundRows = dt.AsEnumerable() .Where(row => row.Field<DateTime>("Datum") >= firstDayOfMonth && row.Field<DateTime>("Datum") <= lastDayOfMonth) .ToArray();
这种Linq的写法不仅更直观,还能在编译期就检查类型错误,比用Select方法的字符串筛选表达式靠谱多了。
内容的提问来源于stack exchange,提问作者Kᴀτᴢ
相关产品推荐
相关产品推荐

