LINQ to SQL "агрегирующее" свойство - PullRequest
4 голосов
/ 31 мая 2011

Допустим, у меня есть таблица Orders и таблица Payments.

Каждый платеж относится к данному заказу: Payment.orderId

Я хочу запросить свои заказы:

var query = from o in db.Orders where o.blah = blah select o;

Но мне также нужна общая сумма, уплаченная за каждый заказ:

var query =  from o in db.Orders 
             where o.blah = blah 
             select new
             {
                 Order = o,
                 totalPaid =  (from p in db.Payments
                               where p.orderId == o.id
                               select p.Amount).Sum()
             };

LINQ to SQL генерирует именно тот запрос SQL, который я хочу.

Моя проблемачто я добавляю поддержку платежей в существующее приложение.Поэтому, чтобы минимизировать влияние кода, я бы хотел, чтобы totalPaid был свойством моего Order класса.

Я подумал о добавлении свойства "manual" и попытался заполнить его во время запроса.Но когда я пишу предложение select, я застрял:

var query =  from o in db.Orders 
             where o.blah = blah 
             select "o with o.totalPaid = (from p in db.Payments <snip>).Sum()"

Как я могу это сделать?

Ответы [ 2 ]

7 голосов
/ 31 мая 2011

Обычно ваш класс Order будет иметь свойство навигации с именем Payments.Используя это, ваше свойство TotalPaid будет выглядеть так:

public double TotalPaid
{
    get { return Payments.Sum(x => x.Amount); }
}

Это решает еще одну проблему: это свойство всегда актуально.Ваш подход будет устаревшим, как только новый платеж будет добавлен к заказу.

Если актуальность не так важна, как сокращение количества обращений к базе данных, вы можете использовать этокод:

private double? _totalPaid;

public double TotalPaid
{
    get
    { 
        if(!_totalPaid.HasValue)
            _totalPaid = Payments.Sum(x => x.Amount);
        return _totalPaid.Value;
    }
}
2 голосов
/ 01 июня 2011

Вы можете добавить EntitySet платежей в класс Orders, который указывает на класс Payments, а также объявить свойство TotalPaid в соответствии с предложением Даниэля Хилгарта.

Но когда вы запрашиваете базу данных для заказов, LinqToSql сделает 1 запрос для каждого заказа, чтобы получить сумму платежей. Обходной путь должен использовать метод DataContext.LoadWith () следующим образом:

DataContext db = new Datacontext(connStr);
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Orders>(o=>o.Payments);
db.LoadOptions = dlo;
var query =  from o in db.Orders 
             where o.blah = blah 
//this will load the payments with the orders in a single query
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...