gpt4 book ai didi

linq - 如何在以编程方式生成的 Linq 表达式中将值绑定(bind)到变量

转载 作者:行者123 更新时间:2023-12-01 16:25:28 25 4
gpt4 key购买 nike

我正在尝试以编程方式生成表达式树(最终将在 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com