实体框架中的LINQ谓词

时间:2014-05-21 10:59:50

标签: c# linq entity-framework

我想调用方法

 query.Range(item => item.Date, filter.Date);

并有方法:

 public static IQueryable<T> Range<T>(this IQueryable<T> query, Func<T, DateTime> func, DateTime range)
    {
       return query.Where(item=> func(item) <= range); // <<-- Error "func(item)"
    }

错误: LINQ to Entities不支持LINQ表达式节点类型“Invoke”。

如何使用功能?

2 个答案:

答案 0 :(得分:3)

写作时

return query.Where(item => func(item) <= range);

然后lambda item => func(item) <= range不是简单的lambda - 它转换为Expression<Func<T,bool>>。执行查询时,EF会尝试将此类表达式转换为SQL代码。不幸的是,它不知道如何在纯SQL中表示func的调用。因此,您会看到此错误。并且您不能在传递给EF的表达式中使用委托调用。

解决方法:而不是

query.Range(item => item.Date, filter.Date)

使用简单(在这种情况下它也更具可读性)

query.Where(item => item.Date <= filter.Date)

更新:您可以手动构建日期过滤器表达式:

public static IQueryable<T> Range<T>(this IQueryable<T> query,
    Expression<Func<T, DateTime>> func, DateTime range)
{            
    var predicate = 
        Expression.Lambda<Func<T, bool>>(
            Expression.LessThanOrEqual(func.Body, Expression.Constant(range)),
            func.Parameters.Single());

    return query.Where(predicate);
}

答案 1 :(得分:0)

您可以使用更通用的approch。

    public IQueryable<T> Filter<T>(Expression<Func<T, bool>> predicate) where T : class
    {
        return db.Set<T>().Where<T>(predicate).AsQueryable<T>();
    }

并称之为:

query.Filter<MyClassIWantToFetch>(item => item.Date <= filter.Date)

并且不要忘记将MyClassIWantToFetch更改为您想要的类型。

相关问题