gpt4 book ai didi

c# - 更改预先存在的 BinaryExpression 中的 ConstantExpression 的值

转载 作者:太空狗 更新时间:2023-10-29 21:13:29 24 4
gpt4 key购买 nike

我有一些代码生成表达式作为数据库中读取的“where”语句传递,我正在尝试加快速度。

下面的示例使用 where 语句来匹配具有传入值的表的 PK:

private Expression MakeWhereForPK(int id)
{
var paramExp = Expression.Parameter(typeof(Brand),"b");

//Expression to get value from the entity
var leftExp = Expression.Property(paramExp,"ID");

//Expression to state the value to match (from the passed in variable)
var rightExp = Expression.Constant(id,typeof(int));

//Expression to compare the two
var whereExp = Expression.Equal(leftExp,rightExp);

return Expression.Lambda<Func<Brand,bool>>(whereExp,paramExp);
}

上面是对问题的简化 - 真正的事情包括获取表进行查询并找到其 PK 等的代码。它实际上在做与您通常在代码中可能做的相同的事情:

ctx.Brands.Where(b => b.ID = id);

这工作正常,但是,在进行测试以优化一些东西时,我发现它相当慢 - 执行上述 1000000 次大约需要 25 秒。如果我省略上面的最后一行会更好(但显然它没有用!),所以它似乎是 Expression.Lamba 花费了大约 2/3 的时间,但其余的也不是很好。

如果所有查询都将同时发生,我可以将其转换为 IN 样式表达式并生成一次,但不幸的是,这是不可能的,所以我希望节省上面的大部分生成,只是重用生成的表达式,但传入不同的 id 值。

请注意,由于这将被传递给 Linq,我无法将表达式编译为具有可在调用时传递的整数参数 - 它必须保留为表达式树。

因此,为了进行计时练习,以下可能是一个简单的版本:

Expression<Func<Brand,bool>> savedExp;

private Expression MakeWhereForPKWithCache(int id)
{
if (savedExp == null)
{
savedExp = MakeWhereForPK(id);
}
else
{
var body = (BinaryExpression)savedExp.Body;
var rightExp = (ConstantExpression)body.Right;

//At this point, value is readonly, so is there some otherway to "inject" id,
//and save on compilation?
rightExp.Value = id;
}

return savedExp;
}

我如何重新使用表达式,只是使用不同的 id 值?

最佳答案

您可以利用表达式树不必只包含简单常量这一事实,它还可以包含访问的属性。因此,您要做的是创建一个访问某些属性值的表达式,并且每次只更改该属性,而不是表达式树。

类似于:

class ExpressionHolder
{
public int Value { get; set; }

public Expression<Func<Brand, bool>> Expr { get; private set; }

public ExpressionHolder()
{
Expr = MakeWhereForPK();
}

private Expression<Func<Brand, bool>> MakeWhereForPK()
{
var paramExp = Expression.Parameter(typeof(Brand), "b");

var leftExp = Expression.Property(paramExp, "ID");

var rightExp = Expression.Property(Expression.Constant(this), "Value");

var whereExp = Expression.Equal(leftExp, rightExp);

return Expression.Lambda<Func<Brand, bool>>(whereExp, paramExp);
}
}

这比您的代码快 500 倍:使用 Dennis 的测量代码,我得到以下结果:

Make expression: 00:00:02.9869921
Replace constant expression: 00:00:02.3332857
Set property: 00:00:00.0056485

关于c# - 更改预先存在的 BinaryExpression 中的 ConstantExpression 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15134009/

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