I would like to be able to reuse fragments of my select lambda expressions in my Entity Framework Core 2.0 queries.
For example:
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();
Since I might want to calculate the CurrentValue
property in other queries (in practice the sub-query is more complex than this), I would ideally like to refactor the above code to something like:
var result = await ctx.Customers
.Select(cust => new CustomerDto {
CustomerId = cust.Id,
CustomerName = cust.Name,
CurrentValue = CalculateCustomerCurrentValueExpr(cust)
})
.ToListAsync();
I have created Linq predicates using a Linq.Expression
, but I have been unable to find a way to use an Expression
as an element of the select statement.
Any help would be much appreciated.
For anyone interested, I ran some test code ten times which produced the following result:
Standard Inline Code: 17ms (58,609 ticks)
With .AsExpandable() and inline code 16ms (58,029 ticks)
With .AsExpandable() and .Invoke() 16ms (58,224 ticks)
I suspect that if more test cycles had been run, the average processing time for all three scenarios would have been the same - at least with the level of accuracy I could measure at (simple StopWatch()
).
Thanks to all contributors, particularly SergeyA for the solution and Ivan Stoev for the simple explanation of .AsExpandable()
You can reuse expressions with AsExpandable extension from LinqKit liblary (http://www.albahari.com/nutshell/linqkit.aspx).
Example:
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With