Supponiamo che io sono una classe che rappresenta righe d'ordine, ad esempioCome si appiattisce una query Linq dopo aver usato il doppio raggruppamento?
public class Line
{
public string Code ;
public string No ; // Invoice Number
public DateTime Date ;
public string Product ;
public decimal Quantity ;
}
e un elenco di linee, ad esempio
List<Line> myList = new List<Line>();
myList.Add(new Line() { Code = "ABC001", No = "1001" ,Date = new DateTime(2012,4,1) , Product = "X", Quantity= 1m});
myList.Add(new Line() { Code = "ABC001", No = "1001" ,Date = new DateTime(2012,4,1) , Product = "Y", Quantity= 1m});
myList.Add(new Line() { Code = "ABC002", No = "1002" ,Date = new DateTime(2012,4,2) , Product = "X", Quantity= 1m});
myList.Add(new Line() { Code = "ABC002", No = "1002" ,Date = new DateTime(2012,4,2) , Product = "Y", Quantity= 1m});
myList.Add(new Line() { Code = "ABC002", No = "1003" ,Date = new DateTime(2012,4,3) , Product = "Z", Quantity= 1m});
myList.Add(new Line() { Code = "ABC002", No = "1004" ,Date = new DateTime(2012,4,4) , Product = "X", Quantity= 1m});
myList.Add(new Line() { Code = "ABC003", No = "1005" ,Date = new DateTime(2012,4,4) , Product = "X", Quantity= 1m});
myList.Add(new Line() { Code = "ABC003", No = "1006" ,Date = new DateTime(2012,4,4) , Product = "X", Quantity= 1m});
myList.Add(new Line() { Code = "ABC003", No = "1006" ,Date = new DateTime(2012,4,4) , Product = "Y", Quantity= 1m});
Sto cercando di recuperare tutte le righe in cui il codice cliente ha più di una fattura. Per fare questo, sono prima di tutto raggruppando per Codice, No e Data e poi raggruppando quello per Codice cliente e per tutti i clienti che hanno due o più record, sto selezionando tutto tranne il primo record.
Come così:
var query1 =
(from r in myList
group r by new { r.Code , r.No , r.Date } into results
group results by new { results.Key.Code } into results2
where results2.Count() > 1
select new
{
results2.Key.Code ,
Count = results2.Count(),
Results = results2.OrderBy(i=>i.Key.Date).Skip(1).ToList()
// Skip the first invoice
}
).ToList();
query1 contiene ora i record corretti, ma avvolto dentro IGrouping e sto avendo difficoltà ottiene i risultati come un List<Line>
ho cercato query1.SelectMany (r = > r.Results) ToList();
ma questo mi lascia ancora con IGrouping ed è lì che sono bloccato.
ho potuto ricorrere al cicli for innestati come in
List<Line> output = new List<Line>();
foreach (var r1 in query1)
{
foreach(var r2 in r1.Results)
foreach(var r3 in r2)
output.Add(r3);
}
ma c'è un/modo migliore Linq?
L'uscita effettiva dovrebbe essere quattro linee come in
// Code No Date Product Quantity
// ABC002 1003 03/04/2012 00:00:00 Z 1
// ABC002 1004 04/04/2012 00:00:00 X 1
// ABC003 1006 04/04/2012 00:00:00 X 1
// ABC003 1006 04/04/2012 00:00:00 Y 1
vorrei cambiare 'results2.ToList() OrderBy (i => i.Key.Date) .Skip (1) .ToList() 'a' results2.OrderBy (i => i.Key.Date) .Skip (1) .ToList() '. Non c'è motivo per la prima chiamata "ToList()". – phoog
@phoog Ho rimosso la prima ToList() perché è corretta in quanto non è necessaria, ma non influenza anche i risultati, quindi ho ancora il mio problema originale. – sgmoore
sì, l'ho postato come commento perché non risponde alla tua domanda. Ho anche pubblicato una risposta qui sotto. – phoog