我希望能够在Entity Framework Core 2.0查询中重用我选择的lambda表达式的片段。
例如:
var result = await ctx.Customers
.Select(cust => new CustomerDto {
CustomerId = cust.Id,
CustomerName = cust.Name,
CurrentValue = cust.Orders
.Where(order => order.OrderDate >= DateTime.Now.AddDays(-30)
.Sum(order => order.TotalValue)
})
.ToListAsync();
由于我可能想在其他查询中计算
CurrentValue
属性(实际上,子查询比这更复杂),因此理想情况下,我希望将上述代码重构为以下形式:var result = await ctx.Customers
.Select(cust => new CustomerDto {
CustomerId = cust.Id,
CustomerName = cust.Name,
CurrentValue = CalculateCustomerCurrentValueExpr(cust)
})
.ToListAsync();
我已经使用
Linq.Expression
创建了Linq谓词,但无法找到将Expression
用作select语句元素的方法。任何帮助将非常感激。
更新-使用.AsExpandable()/。Invoke()的性能
对于任何有兴趣的人,我运行了十次测试代码,均得出以下结果:
Standard Inline Code: 17ms (58,609 ticks)With .AsExpandable() and inline code 16ms (58,029 ticks)With .AsExpandable() and .Invoke() 16ms (58,224 ticks)
我怀疑如果运行了更多的测试周期,那么所有这三种情况的平均处理时间都将是相同的-至少达到我可以测量的准确度(简单
StopWatch()
)。感谢所有贡献者,特别是解决方案的SergeyA和Ivan Stoev的
.AsExpandable()
的简单解释 最佳答案
您可以重复使用LinqKit liblary(http://www.albahari.com/nutshell/linqkit.aspx)中具有AsExpandable扩展名的表达式。
例:
Expression<Func<Customer,long>> func = c => c.Orders
.Where(order => order.OrderDate >= DateTime.Now.AddDays(-30)
.Sum(order => order.TotalValue);
var result = await ctx.Customers
.AsExpandable() // this allow to unwrap injected expression
.Select(cust => new CustomerDto {
CustomerId = cust.Id,
CustomerName = cust.Name,
CurrentValue = func.Invoke(cust) // this inject predefined expression
})
.ToListAsync();