我编写了这个过滤器来只从数据库中获取与特定时间段匹配的文档:
Period实体很简单,包含两个属性:DateFrom和DateTo。
我需要从 lambdas 构建一个过滤器,每个Period用于构建过滤器。
过滤器在完全构建后必须如下所示:
ObjectSet.Where(d =>
(d.Date >= Period1.DateFrom && d.Date <= Period1.DateTo)
|| (d.Date >= Period2.DateFrom && d.Date <= Period2.DateTo)
|| (d.Date >= Period3.DateFrom && d.Date <= Period3.DateTo));
如您所料,我必须动态构建此过滤器,因为构建过滤器的提交周期数可能会有所不同。
(以下是Expression
我用来组合 lambdas 的(每个时间段都已提交构建过滤器)
private Expression<Func<T, bool>> CombineWithOr<T>(
Expression<Func<T, bool>> firstExpression,
Expression<Func<T, bool>> secondExpression)
{
var parameter = Expression.Parameter(typeof(T), "x");
var resultBody = Expression.Or(
Expression.Invoke(firstExpression, parameter),
Expression.Invoke(secondExpression, parameter));
return Expression.Lambda<Func<T, bool>>(resultBody, parameter);
}
在这里,我将每个 lambda 组合在一起,以便添加到文档过滤器中:
public IList<Document> GetDocuments(IList<Periods> periods)
{
Expression<Func<Document, bool>> resultExpression = n => false;
foreach (var submittedPeriod in periods)
{
var period = submittedPeriod;
Expression<Func<Document, bool>> expression =
d => (d.Date >= period.DateFrom && d.Date <= period.DateTo);
resultExpression = this.CombineWithOr(resultExpression, expression);
}
var query = this.ObjectSet.Where(resultExpression.Compile());
}
问题是,当我启动查询的延迟执行时......
var documents = query.ToList();
...我查看生成的 SQL,SELECT 语句中没有添加任何内容。
如果我执行查询而不编译生成的表达式,如下所示:
var query = this.ObjectSet.Where(resultExpression);
我得到这个例外:
LINQ to Entities 不支持 LINQ 表达式节点类型“Invoke”。
这意味着 Linq-To-Entities 查询提供程序不知道如何将我的过滤器转换为 SQL 代码。
现在困扰我的是,从属于我的实体模式的实体(文档和期间)进行的这种简单的 DateTime 比较如何会弄乱提供者?
有什么想法可以实现这样的过滤吗?