Могу ли я сослаться на вычисляемые столбцы в запросе Linq to Sql? - PullRequest
2 голосов
/ 07 февраля 2011

У меня есть следующая схема:

product  
- productID (PK)  
- name  
- units  

purchase  
- purchaseID (PF)  
- productID (FK)  
- soldUnits  
- woUnits  

boxContents  
- boxID (PK)  
- puchaseID (FK)  
- count

и следующий запрос Linq to SQL:

 var qStockLevel = from pr in db.products
    select new
    {
        pr.productID,
        pr.name,
        totalUnits = (from pu in db.purchases
                      where pu.productID == pr.productID
                      select pu).Count() * pr.units,

    sold = (from pr2 in db.products
            join pu in db.purchases on pr.productID equals pu.productID into pp
            where pr2.productID == pr.productID
            from pu2 in pp.DefaultIfEmpty()
            select (int?) pu2.soldUnits ?? 0).Sum(),

    writtenOff = (from pr2 in db.products
                join pu in db.purchases on pr.productID equals pu.productID into pp
                where pr2.productID == pr.productID
                from pu in pp.DefaultIfEmpty()
                select (int?)pu.woUnits ?? 0).Sum(),

    onDisplay = (from pr2 in db.products
                join bc in db.boxContents on pr.productID equals bc.purchase.productID into bp
                where pr2.productID == pr.productID
                from bc in bp.DefaultIfEmpty()
                select (int?)bc.count ?? 0).Sum(),

    available = (totalUnits - sold - writtenOff - onDisplay),
};

«Доступный» столбец в конце не работает, но я включил его, чтобы проиллюстрировать то, что я пытаюсь достичь - столбец, рассчитанный по уже сгенерированным столбцам. Это возможно? Я мог сделать это на уровне представления, но хотел проверить, сработает ли это сначала.

Кроме того, на мой взгляд (новичок в Linq), запрос выглядит неэффективным, поскольку я повторяю себя в создании столбцов writeOff и sold. Есть ли лучший способ добиться этого, когда у меня есть агрегатные функции.

Спасибо.

EDIT

Еще одна вещь - я хочу возвращать только те строки, где «доступно»> 0.

Ответы [ 2 ]

2 голосов
/ 07 февраля 2011

Вот запрос, который должен делать то, что вы хотите.

(Примечание: предполагается, что вы установили связь между Product -> Purchases -> BoxContents в конструкторе DBML.)

var query = from product in context.Products
            where 
            (
                product.Purchases.Count() * product.units -
                product.Purchases.Sum(purchase => purchase.soldUnits ?? 0) -
                product.Purchases.Sum(purchase => purchase.woUnits ?? 0) -
                product.Purchases.SelectMany(purchase => purchase.BoxContents).Sum(bc => bc.count ?? 0)
            ) > 0
            select product;

И, к вашему сведению, вот один способ, которым вы могли бы настроить свой Product класс.

(Возможно, вы захотите использовать DataLoadOptions.LoadWith() для полной загрузки дочерних элементов Product.)

public partial class Product
{
    public int TotalUnits
    {
        get { return this.Purchases.Count * this.units ?? 0; }
    }

    public int Sold
    {
        get { return this.Purchases.Sum(p => p.soldUnits ?? 0); }
    }

    public int WrittenOff
    {
        get { return this.Purchases.Sum(p => p.woUnits ?? 0); }
    }

    public int OnDisplay
    {
        get { return this.Purchases.SelectMany(p => p.BoxContents).Sum(b => b.count ?? 0); }
    }

    public int Available
    {
        get { return TotalUnits - Sold - WrittenOff - OnDisplay; }
    }
}
0 голосов
/ 07 февраля 2011

сделайте секунду, выбрав new {} для последней строки (вам нужно будет снова скопировать все поля, которые вам нужны во втором наборе), и после этого добавить предложение where

РЕДАКТИРОВАТЬ: на самом деле не связано, но похоже, что вы могли бы извлечь выгоду из нового столбца, содержащего доступное значение (с Linq To Sql и INotityPropertyChanging это должно быть довольно легко реализовать)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...