C#在LINQ查询中调用自定义日期校验方法时传入参数为空问题排查
问题原因
- 如果你使用的是
IQueryable类型的数据源(最常见的为Entity Framework的数据库查询对象):LINQ to Entities 需要将Where条件的表达式树转换为可执行的SQL语句,你自定义的IsDateBetween方法无法被EF的表达式解析器识别,解析过程中外部变量的传递逻辑会被忽略,最终方法执行时拿到的min、max参数就会是null。 - 如果是内存集合(
IEnumerable类型)的场景:大概率是延迟执行的变量捕获问题,如果你在定义完LINQ查询语句之后、实际迭代执行查询之前,修改了startDateS和startDateF的值为null,那么查询真正执行时会捕获到修改后的值。
解决办法
方案1:在数据库侧完成过滤(推荐,避免全表拉取)
不要使用自定义方法,直接把日期判断逻辑写在Where表达式内,同时提前完成字符串到日期的类型转换,避免表达式树内的转换逻辑无法被EF解析:
// 提前在外层完成日期转换,逻辑和原方法保持一致 DateTime? minDate = string.IsNullOrEmpty(startDateS) ? null : Convert.ToDateTime(startDateS); DateTime? maxDate = string.IsNullOrEmpty(startDateF) ? null : Convert.ToDateTime(startDateF); var policiesT = policies.Where(x => (!minDate.HasValue || x.StartofInsurance > minDate.Value) && (!maxDate.HasValue || x.StartofInsurance < maxDate.Value) );
如果需要包含日期区间的边界,把>和<改为>=和<=即可。
方案2:拉取到内存后再过滤
如果你的数据量很小,或者确实需要使用自定义方法,可以在调用Where前先调用AsEnumerable(),把IQueryable转换为内存集合,之后的LINQ操作会走LINQ to Objects逻辑,自定义方法可以正常执行,参数也会正常传递:
var policiesT = policies.AsEnumerable().Where(x=>IsDateBetween(x.StartofInsurance,startDateS,startDateF));
内容的提问来源于stack exchange,提问作者Sadullah DOĞAN
相关产品推荐
相关产品推荐

