LINQ to SQL и общая сумма по упорядоченным результатам
Я хочу отобразить историю учета клиентов в DataGridView
, и я хочу иметь столбец, который отображает текущую итоговую сумму для их баланса. Старый способ, которым я это делал, состоял в получении данных, переходе по данным и добавлении строк в DataGridView
один за другим и вычислении текущей суммы в то время. Ламе. Я бы предпочел использовать LINQ to SQL или LINQ, если это невозможно с LINQ to SQL, чтобы выяснить текущие итоги, чтобы я мог просто установить 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, казалось, шел по той же самой вещи, что и я, но я не вижу, как принятый/единственный ответ решает мою проблему.
Любые идеи о том, как это сделать?
Edit
Комбинируя ответы от 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
});
Ответы
Ответ 1
Использование закрытий и анонимного метода:
List<Item> myList = FetchDataFromDatabase();
decimal currentTotal = 0;
var query = myList
.OrderBy(i => i.Date)
.Select(i =>
{
currentTotal += i.Amount;
return new {
Date = i.Date,
Amount = i.Amount,
RunningTotal = currentTotal
};
}
);
foreach (var item in query)
{
//do with item
}
Ответ 2
Как насчет этого: (кредит идет этот источник)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
delegate string CreateGroupingDelegate(int i);
static void Main(string[] args)
{
List<int> list = new List<int>() { 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 69, 2007};
int running_total = 0;
var result_set =
from x in list
select new
{
num = x,
running_total = (running_total = running_total + x)
};
foreach (var v in result_set)
{
Console.WriteLine( "list element: {0}, total so far: {1}",
v.num,
v.running_total);
}
Console.ReadLine();
}
}
}
Ответ 3
Если это еще не ответили, у меня есть решение, которое я использовал в своих проектах. Это очень похоже на группу разделенных Oracle. Ключ должен заключить, что предложение where в текущем итоге соответствует списку orig, затем группирует его по дате.
var itemList = GetItemsFromDBYadaYadaYada();
var withRuningTotals = from i in itemList
select i.Date, i.Amount,
Runningtotal = itemList.Where( x=> x.Date == i.Date).
GroupBy(x=> x.Date).
Select(DateGroup=> DateGroup.Sum(x=> x.Amount)).Single();
Ответ 4
Агрегат можно также использовать для получения итоговой суммы:
var src = new [] { 1, 4, 3, 2 };
var running = src.Aggregate(new List<int>(), (a, i) => {
a.Add(a.Count == 0 ? i : a.Last() + i);
return a;
});
Ответ 5
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var list = new List<int>{1, 5, 4, 6, 8, 11, 3, 12};
int running_total = 0;
list.ForEach(x=> Console.WriteLine(running_total = x+running_total));
}
}