LINQ to SQL e um total em execução nos resultados ordenados

Eu quero exibir o histórico de contabilidade de um cliente em um DataGridView e eu quero ter uma coluna que exibe o total em execução para o seu saldo. A maneira antiga como fiz isso foi obtendo os dados, fazendo o loop pelos dados e adicionando linhas ao DataGridView um a um, e calculando o total em execução naquele momento. Coxo. Eu prefiro usar LINQ to SQL, ou LINQ se não for possível com o LINQ to SQL, para descobrir os totais em execução para que eu possa definir DataGridView.DataSource para meus dados.

Este é um exemplo super simplificado do que estou fotografando. Diga que eu tenho a seguinte aula.

 class Item { public DateTime Date { get; set; } public decimal Amount { get; set; } public decimal RunningTotal { get; set; } } 

Gostaria de uma instrução L2S ou LINQ, que poderia gerar resultados semelhantes a este:

  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 

Observe que pode haver vários itens com a mesma data (12-02-2009). Os resultados devem ser classificados por data antes dos totais em execução serem calculados. Eu estou supondo que isso significa que vou precisar de duas instruções, uma para obter os dados e classificá-los e um segundo para executar o cálculo do total em execução.

Eu estava esperando Aggregate faria o truque, mas não funciona como eu estava esperando. Ou talvez eu simplesmente não conseguisse descobrir.

Esta questão parecia estar indo atrás da mesma coisa que eu queria, mas não vejo como a resposta aceita / resolve o meu problema.

Alguma idéia de como fazer isso?

Editar Combinando as respostas de Alex e DOK, é com isso que acabei:

 decimal runningTotal = 0; var results = FetchDataFromDatabase() .OrderBy(item => item.Date) .Select(item => new Item { Amount = item.Amount, Date = item.Date, RunningTotal = runningTotal += item.Amount }); 

Usando fechamentos e método anônimo:

 List 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 } 

Que tal isso: (crédito vai para essa fonte )

 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 list = new List() { 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(); } } } 

Caso isso ainda não tenha sido respondido, tenho uma solução que tenho usado em meus projetos. Isso é muito semelhante a um grupo particionado do Oracle. A chave é que a cláusula where no total em execução corresponda à lista original e, em seguida, agrupe-a por data.

 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(); 

Agregado também pode ser usado para obter um total em execução:

 var src = new [] { 1, 4, 3, 2 }; var running = src.Aggregate(new List(), (a, i) => { a.Add(a.Count == 0 ? i : a.Last() + i); return a; }); 
 using System; using System.Linq; using System.Collections.Generic; public class Program { public static void Main() { var list = new List{1, 5, 4, 6, 8, 11, 3, 12}; int running_total = 0; list.ForEach(x=> Console.WriteLine(running_total = x+running_total)); } }