[英]Break out part of linq-to-sql expression to a separate function
我有两个实体类:
public class Invoice
{
public int ID { get; set;}
public int Amount { get { return InvoiceLines.Sum(il => il.Amount); }}
public EntitySet<InvoiceLines> InvoiceLines {get;set;};
}
public class InvoiceLine
{
public Invoice Invoice {get;set;}
public int InvoiceID {get;set;}
public int Amount {get;set;}
public string SomeHugeString {get;set;}
}
(真正的类是sqlmetal生成的,在这里我将其缩短到此处)。
查询所有金额:
var amounts = from i in invoice select i.Amount;
这将导致所有发票行被延迟加载,每个发票调用一个数据库。 我可以使用数据加载选项解决它,但这将导致读取整个InvoiceLine对象,包括SomeHugeString
。
在查询中重复金额计算将获得良好的SQL转换:
var amounts = from i in invoice select i.InvoiceLines.Sum(il => il.Amount);
我很想让linq-to-sql以某种方式从函数/属性中获取表达式树的一部分。 有没有一种方法可以重写Invoice.Amount
以便第一个金额查询将提供与第二个相同的SQL转换?
您可以使用AsExpandable()
做类似的事情 :
Expression<Func<Invoice, int>> getAmount =
i => i.InvoiceLines.Sum(il => il.Amount);
var amounts = from i in invoice.AsExpandable() select getAmount.Invoke(i);
您可以使用IQueryable
接口创建自己的函数。
我使用了标准的NorthWind DB:
public static class LinqExtensions
{
public static IQueryable<int> CalculateAmounts(this IQueryable<Order> order)
{
return from o in order select o.Order_Details.Sum(i => i.Quantity);
}
}
var amounts = (from o in context.Orders select o).CalculateAmounts();
这段代码生成这样的SQL:
SELECT [t2].[value]
FROM [dbo].[Orders] AS [t0]
OUTER APPLY (
SELECT SUM(CONVERT(Int,[t1].[Quantity])) AS [value]
FROM [dbo].[Order Details] AS [t1]
WHERE [t1].[OrderID] = [t0].[OrderID]
) AS [t2]
我建议您将“ SomeHugeString”属性设置为延迟加载。 这样,您可以加载InvoiceLine
而无需获取大字符串,这意味着您可以使用DataLoadOptions.LoadWith()
:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.