- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一些代码生成表达式作为数据库中读取的“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/
问了这个问题How to reach CSS zen? ,我现在明白我遇到的问题大多与定位有关。我发现一些文章说 CSS 作为布局系统并不总是足够好。 http://echochamber.me/vi
我是一名优秀的程序员,十分优秀!