我有一个需要在所有地方重复使用的查询,我需要改变用于连接的属性/列。
我希望能够做的是:
query = RestrictByProp(query, x=>x.ID);
一个极其简化的 RestrictByProp()
可能是*:
private static IQueryable<Role> RestrictByProp(IQueryable<Role> query,
Func<Role, int> selector)
{
return query.Where(x => selector(x) == 1);
}
问题是,即使是这个简单的实现也会导致运行时异常:
Method 'System.Object DynamicInvoke(System.Object[])' has no
supported translation to SQL.
**(这里我只是添加了一个简单的“where”子句——在我的真实代码中,我将使用 lambda 来选择要用于连接的属性)。*
我觉得这很奇怪,因为如果成员访问 lambda 是内联完成的,那就没问题了:
private static IQueryable<Role> RestrictByID(IQueryable<Role> query)
{
return query.Where(x=> x.ID == 1);
}
如果您传入 Expression<Func<Role, bool>>
,LINQ to SQL 也很高兴(即当参数为 x=>x.ID == 1
时)但这会使对象失效,因为我需要在查询中确定右侧操作数的值。
有没有办法以某种方式修改 RestrictByProp()
中的 lambda 表达式?以便 LINQ to SQL 知道如何生成 SQL?
最佳答案
首先,您需要更改您的方法签名:
private static IQueryable<Role> RestrictByProp(IQueryable<Role> query,
Expression<Func<Role, int>> selector)
这意味着您的 lambda 表达式将转换为表达式树而不是委托(delegate)。
然后您需要构建一个 Expression<Func<Role, bool>>
来自现有的表达式树。
它看起来像这样:
LambdaExpression lambda = (LambdaExpression) selector;
var predicate = Expression.Equal(selector, Expression.Constant(1));
var lambdaPredicate = Expression.Lambda<Func<Role, bool>>(predicate,
lambda.Parameters);
return query.Where(lambdaPredicate);
关于c# - 使用成员访问 lambda 表达式参数化 LINQ to SQL 谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3441422/