繁体   English   中英

将linq-to-sql表达式的一部分分解为一个单独的函数

[英]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()

通过右键单击单个属性,选择属性,然后将“延迟加载”属性设置为“ True”,将其设置为延迟加载

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM