Разбить часть выражения linq-to-sql на отдельную функцию - PullRequest
2 голосов
/ 30 октября 2011

У меня есть два класса сущностей:

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, что и второй?

Ответы [ 3 ]

2 голосов
/ 30 октября 2011

Вы можете сделать что-то подобное, используя AsExpandable() из LINQKit :

Expression<Func<Invoice, int>> getAmount =
    i => i.InvoiceLines.Sum(il => il.Amount);

var amounts = from i in invoice.AsExpandable() select getAmount.Invoke(i);
1 голос
/ 31 октября 2011

Я бы посоветовал вам установить свойство SomeHugeString для отложенной загрузки.Таким образом, вы можете загрузить InvoiceLine без получения этой огромной строки, что означает, что вы можете использовать DataLoadOptions.LoadWith():

Set a single property to be delay loaded by right clicking it, selecting properties and then setting the Delay Loaded property to True

1 голос
/ 31 октября 2011

Вы можете создавать свои собственные функции, используя IQueryable интерфейс.

Я использовал стандартную базу данных NorthWind:

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...