2011-05-31 133 views
4

假设我有一个表Orders和一个表PaymentsLINQ to SQL“聚合”属性

每次付款涉及给定的顺序: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()" 

我怎么能这样做?

+0

也许使用'Aggregate'方法而不是'Sum'一个?注意确定'选择'一些字符串''虽然... – leppie 2011-05-31 15:04:39

+0

跛脚,这不是一个字符串,这是我想要实现,但无法找到如何编码;-) – 2011-05-31 15:15:59

回答

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; 
    } 
} 
+0

+1:但可能'付款。 Sum(x => x.Amount)':) – leppie 2011-05-31 15:06:48

+0

@leppie:对,你是。 – 2011-05-31 15:07:29

+0

我想你错过了'使用System.Linq;'。 – 2011-05-31 15:32:53

2

您可以添加一个支付EntitySet的诠释订单类指向Payments类,并根据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