如何使用方法在Entity Framework Core中的属性上添加过滤器?

时间:2018-02-20 12:23:54

标签: asp.net-core entity-framework-core

我需要有条件地在查询中的特定日期添加过滤器。有共同的先决条件,过滤器将是相同的。因此,我希望公共代码位于一个方法中,该方法可以执行这些检查,然后让消费者传递应该应用过滤器的属性(可以应用于多个)。

这是我的代码的简化版本。

var query = dbContext.Documents.AsQueryable();

query = FilterDocumentsByDate(query, x => x.CreatedDate);
query = FilterDocumentsByDate(query, x => x.SubmittedDate);

private IQueryable<Document> FilterDocumentsByDate(IQueryable<Document> query, Func<Document, DateTime> propertyToSearch)
{
    query = query.Where(x => propertyToSearch(x).Year > 2000);
    return query;
}

当我在SQL分析器中查看查询时,我可以看到查询缺少WHERE子句(因此正在检索所有文档并且过滤器正在内存中完成)。如果我在两个日期内联复制/粘贴代码(而不是两次调用方法),那么两个日期的WHERE子句都包含在查询中。

是否无法通过在Func中传递属性来向IQueryable添加WHERE条件,该属性可以通过实体框架正确转换为SQL?

1 个答案:

答案 0 :(得分:5)

EF无法理解您的查询,因此它会破坏并在内存中执行WHERE子句。

解决方案是创建动态表达式。

var query = dbContext.Documents.AsQueryable();

query = FilterDocumentsByDate(query, x => x.CreatedDate.Year);
query = FilterDocumentsByDate(query, x => x.SubmittedDate.Year);

private IQueryable<Document> FilterDocumentsByDate(IQueryable<Document> query, Expression<Func<Document, int>> expression)
{
    var parameter = expression.Parameters.FirstOrDefault();
    Expression comparisonExpression = Expression.Equal(expression.Body, Expression.Constant(2000));
    Expression<Func<Document, bool>> exp = Expression.Lambda<Func<Document, bool>>(comparisonExpression, parameter);

    query = query.Where(exp);
    return query;
}

对不起,我自己没有运行,但这应该创建WHERE语句。让我知道它是怎么回事。

相关问题