问题描述
执行查询时:
rs.Select(x => x.id).ToArray();
我获得此错误:
LINQ在Linq中不支持Linq表达节点类型'Indoke'
这是生成错误的方法(可能 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(); }
怎么了?
推荐答案
要做您想做的事情,您需要做类似的事情:
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; }
您可以看到,您需要进行一些表达树木管道.您以与以前相同的方式调用该方法.
现在...真的可以使用 linqkit 按 @jbl建议?是的...通过摇晃魔杖...
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方法的使用.
问题描述
When I execute my query:
rs.Select(x => x.id).ToArray();
I obtain this error:
The LINQ expression node type 'Invoke' is not supported in LINQ to Entities
This is the method that generates the error (probably 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; }
I invoke the method in this mode:
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(); }
What is wrong?
推荐答案
To do what you want you will need to do something like:
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; }
As you can see you'll need to do some expression-tree plumbing. You call the method in the same way as before.
Now... is it really possible to use LinqKit as suggested by @jbl? Yes... By shaking a little the magic wand...
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; }
Note the use of the Invoke() and Expand() LinqKit methods.