【问题标题】:Error "The LINQ expression node type 'Invoke' is not supported in LINQ to Entities" in where clause inside the method方法内的 where 子句中出现错误“LINQ to Entities 不支持 LINQ 表达式节点类型 'Invoke'”
【发布时间】:2015-04-09 13:34:31
【问题描述】:

当我执行查询时:

rs.Select(x => x.id).ToArray();

我收到此错误:

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

这是产生错误的方法(可能是func(x)):

public IQueryable<TEntity> Compare<TEntity>(IQueryable<TEntity> source, Func<TEntity, int> func)
{
     IQueryable<TEntity> res = source;

     if (!this.LBoundIsNull) res = res.Where(x => func(x) >= _lBound);
     if (!this.UBoundIsNull) res = res.Where(x => func(x) <= _uBound);

     return res;
}

我在这种模式下调用方法:

Document doc = new Document();
doc.Number = new RangeValues(lBound, null);

using (MyEntities db = new MyEntities())
{
    var rs = db.documents;
    if (doc.Number != null) rs = doc.Numero.Compare(rs, x => x.number);

    long[] id = rs.Select(x => x.id).ToArray();
}

怎么了?

【问题讨论】:

  • func(x) 被翻译成Sql 用户定义的函数调用?
  • 您收到的错误消息告诉您确切地出了什么问题。 EF 不支持调用函数。
  • jblfunc(x)用于检索属性的值(本例为x.number)。
  • @Gigi 你不能那样做......你需要做一些表达式树管道来做到这一点。
  • LinqKit 在这里应该有所帮助:github.com/scottksmith95/LINQKit

标签: c# linq entity-framework linq-to-entities


【解决方案1】:

要做你想做的事,你需要做一些类似的事情:

public static IQueryable<TEntity> Compare<TEntity>(IQueryable<TEntity> source, Expression<Func<TEntity, int>> func)
{
    IQueryable<TEntity> res = source;

    if (!LBoundIsNull) 
    {
        Expression ge = Expression.GreaterThanOrEqual(func.Body, Expression.Constant(_lBound));
        var lambda = Expression.Lambda<Func<TEntity, bool>>(ge, func.Parameters);
        res = res.Where(lambda);
    }

    if (!UBoundIsNull)
    {
        Expression le = Expression.LessThanOrEqual(func.Body, Expression.Constant(_uBound));
        var lambda = Expression.Lambda<Func<TEntity, bool>>(le, func.Parameters);
        res = res.Where(lambda);
    }

    return res;
}

如您所见,您需要做一些表达式树管道。你调用这个方法的方式和以前一样。

现在...真的可以按照@jbl 的建议使用LinqKit 吗?是的...摇一点魔杖...

using LinqKit;

public static IQueryable<TEntity> Compare<TEntity>(IQueryable<TEntity> source, Expression<Func<TEntity, int>> func)
{
    IQueryable<TEntity> res = source;

    if (!LBoundIsNull)
    {
        Expression<Func<TEntity, bool>> lambda = x => func.Invoke(x) >= _lBound;
        res = res.Where(lambda.Expand());
    }

    if (!UBoundIsNull)
    {
        Expression<Func<TEntity, bool>> lambda = x => func.Invoke(x) <= _uBound;
        res = res.Where(lambda.Expand());
    }

    return res;
}

注意Invoke()Expand() LinqKit 方法的使用。

【讨论】:

  • @xantos 没有 LinqKit 的解决方案是完美而优雅的。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 2011-07-14
  • 2018-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多