我希望能够在我的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语句元素的方法。
非常感谢任何帮助。
对于任何感兴趣的人,我运行了十次测试代码,产生了以下结果:
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()
的简单解释
答案 0 :(得分:3)
您可以重复使用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();
答案 1 :(得分:0)
我将表达式存储在静态文件中,并重用我需要它们的表达式,以确保包含所有相关数据。也许这对你也有用
在 GetStore()中,我重用了一个名为 ClientAccess 的表达式,并将其传递给 ShopExpressions 中的表达式。
GetPage()使用简单的直接实现。
<强> ShopExpressions.cs 强>:
* * * * * cd /home/arifur/workspace_python/erpdatabasebackup && bash backup_database.sh
<强> Controller.cs 强>:
public static IQueryable<IStore> StoreLite(IQueryable<IStore> dbSet)
{
var result = dbSet
.Include(str => str.VATs)
.ThenInclude(vat => vat.VAT)
.ThenInclude(vat => vat.Culture)
.ThenInclude(cult => cult.Items)
.ThenInclude(itm => itm.Culture)
.Include(str => str.Options)
.ThenInclude(opt => opt.Items)
.ThenInclude(itm => itm.Option)
.Include(str => str.Cultures)
.ThenInclude(cult => cult.Items)
.ThenInclude(itm => itm.Culture)
.ThenInclude(cult => cult.Items)
.ThenInclude(itm => itm.Culture)
.Include(str => str.Pages)
.ThenInclude(page => page.Sections)
.ThenInclude(section => section.Elements);
return result;
}
public static IQueryable<IStore> Store(IQueryable<IStore> dbSet)
{
var result = StoreLite(dbSet)
.Include(str => str.Categorys)
.ThenInclude(cat => cat.Products)
.ThenInclude(prd => prd.InfoItems)
.ThenInclude(itm => itm.Culture)
.ThenInclude(cult => cult.Items)
.ThenInclude(itm => itm.Culture);
return result;
}
public static IQueryable<IPage> Page(IQueryable<IPage> dbSet)
{
var result = dbSet
.Include(page => page.Sections)
.ThenInclude(sec => sec.Elements)
.Include(page => page.CSS)
.Include(page => page.Script)
.Include(page => page.Meta);
return result;
}