假设我有一个Orders
表和一个Payments
表。
每次付款都与给定的订单有关:Payment.orgderId
我想查询我的订单:
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()"
我该怎么做?
通常,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;
}
}
您可以在指向payments类的Orders类中添加一个payments EntitySet,并按照Daniel Hilgarth的建议声明TotalPayed属性。
但当您在数据库中查询订单时,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