作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试以编程方式生成表达式树(最终将在 Linq-to-entity 框架中使用)。
我可以让查询正常工作,但有一个异常(exception) - 它没有参数化查询 - 我希望 Sql Server 查询计划重用。
我读到,为了使生成的 sql 参数化,表达式需要根据变量进行比较。但是,我无法弄清楚如何将值分配给表达式树中的变量。如果我只使用 Expression.Constant
它会起作用(但没有参数化)。
所以基本上:
public Expression<Func<T, bool>> FooEquals<T>(
Expression<Func<T, int>> propertyExpression, int value)
{
ParameterExpression param = propertyExpression.Parameters.Single();
int targetValueForEqualityComparison = 9;
//There's some "special sauce" here which is why I don't
//use propertyExpression directly
var body = Expression.Property(param, GetPropertyName(propertyExpression));
//If I just use Expression.Constant, it works, but doesn't parametrize.
//var equalExpression = ParameterExpression.Equal(body,
// Expression.Constant(targetValueForEqualityComparison, typeof(int)));
var variable = Expression
.Variable(typeof(int), "targetValueForEqualityComparison");
var assigned = Expression.Assign(variable,
Expression.Constant(targetValueForEqualityComparison, typeof(int)));
//throws InvalidOperaitonException: "The parameter was not bound in the
//specified Linq to Entities query expression
var equalExpression = ParameterExpression.Equal(body, variable);
//throws NotSupportedException: "Unknown LINQ expression of type 'Assign'.
var equalExpression = ParameterExpression.Equal(body, assigned);
return Expression.Lambda<Func<T, bool>>(equalExpression, param);
}
如何正确地将值绑定(bind)到变量表达式,以便 Linq-to-EntityFramework 参数化查询?
最佳答案
我继续尝试,因为我很好奇。以下似乎导致相同的 SQL,至少在与 Linq-to-SQL 一起使用时(LINQPad 比 EF 更容易做到)。我想它应该与 EF 一样工作。
似乎是一种非常复杂的方式来传递一个整数,但因为这是编译器为普通 lambda 函数生成的内容,我猜这就是 SQL 生成器寻找的内容。
// Given this class, which is equivalent to the compiler-generated class
class Holder {
public int AnInteger;
}
int id = 1;
// You get the same SQL with a plain lambda function
var query = db.Items.Where(i => i.Id == id);
// or with a handwritten expression:
var arg = Expression.Parameter(typeof(Item), "i");
var paramHolder = new Holder { AnInteger = id };
// essentially, (i) => i.Id == paramHolder.AnInteger
var lambda = Expression.Lambda<Func<Item, bool>>(
Expression.Equal(
Expression.Property(arg, "Id"),
Expression.Field(
Expression.Constant(paramHolder), "AnInteger")),
arg);
// the SQL this translates to is equivalent to that of the first query
var query2 = db.Items.Where(lambda);
关于linq - 如何在以编程方式生成的 Linq 表达式中将值绑定(bind)到变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19260105/
我是一名优秀的程序员,十分优秀!