【发布时间】:2010-12-22 12:40:48
【问题描述】:
我想在DataGridView 中显示客户的会计历史记录,并且我希望有一列显示其余额的累计。我这样做的旧方法是获取数据,遍历数据,并将行逐一添加到DataGridView 并计算当时的运行总数。瘸。我宁愿使用 LINQ to SQL,或者如果不能使用 LINQ to SQL,则使用 LINQ 来计算运行总数,这样我就可以将DataGridView.DataSource 设置为我的数据。
这是我正在拍摄的一个超级简化的示例。假设我有以下课程。
class Item
{
public DateTime Date { get; set; }
public decimal Amount { get; set; }
public decimal RunningTotal { get; set; }
}
我想要一个 L2S 或 LINQ 语句,它可以生成如下所示的结果:
Date Amount RunningTotal
12-01-2009 5 5
12-02-2009 -5 0
12-02-2009 10 10
12-03-2009 5 15
12-04-2009 -15 0
请注意,可以有多个项目具有相同的日期 (12-02-2009)。在计算运行总计之前,应按日期对结果进行排序。我猜这意味着我需要两条语句,一条用于获取数据并对其进行排序,另一条用于执行运行总计。
我希望Aggregate 能做到这一点,但它并没有像我希望的那样工作。或者我只是想不通。
这个question 似乎在追求我想要的同一件事,但我看不出接受/唯一的答案如何解决我的问题。
关于如何实现这一点的任何想法?
编辑 结合 Alex 和 DOK 的答案,我得出了以下结论:
decimal runningTotal = 0;
var results = FetchDataFromDatabase()
.OrderBy(item => item.Date)
.Select(item => new Item
{
Amount = item.Amount,
Date = item.Date,
RunningTotal = runningTotal += item.Amount
});
【问题讨论】:
-
感谢新工具! : RunningTotal = runningTotal += item.Amount
-
这个解决方案不会强制在客户端执行吗? (即它必须拉下整个结果集才能得到正确的答案?)——如果在 SQL 服务器上完成类似这样的事情,似乎性能会更高......
-
使用查询外部的变量是非常危险的!因为
results变量是IEnumerable类型,所以它的执行将被推迟 到以后。如果在此之前更改runningTotal的值,则生成的查询将不再正确。为了安全起见,您需要立即枚举它(列表或数组)。在这里使用简单的foreach循环没有任何问题。 -
正是我试图解决的问题。感谢您在六年前提出这个问题!
标签: c# linq linq-to-sql linq-to-objects