LINQ to SQL“聚合”属性

时间:2011-05-31 15:00:35

标签: c# .net linq linq-to-sql

假设我有一张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类的属性。

我想添加一个“手动”属性,并尝试在查询时填写它。 但编写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 个答案:

答案 0 :(得分:7)

通常,您的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;
    }
}

答案 1 :(得分:2)

您可以在Orders类中添加指向Payments类的付款EntitySet,也可以按照Daniel Hilgarth的建议声明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