2011-08-09 63 views
1

我正在與Linq的GroupBy廝殺。我想我不能用一種表達方式做,但不知道如何解決問題。GroupBy與Linq到對象

我有以下2類:

public class Shipment { 
    public string PortOfOrigin{get;set;} 
    public string PortOfDestination{get;set;} 
    public ICollection<Invoice> Invoices{get;set;} 
} 

public class Invoice{ 
    public string InvoicePeriod {get;set;} 
    public decimal Amount {get;set;} 
} 

我有貨,所有有發票的集合的集合。這是一個例子。

List<Shipment> shipments = new List<Shipment> 
{ 
    new Shipment { PortOfOrigin = "USLOS", PortOfDestionation = "UKLON", 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 1000}, 
      new Invoice{InvoicePeriod = "201106", Amount = 2000}, 
      new Invoice{InvoicePeriod = "201107", Amount = 1000} 
     } 
    }, 
    new Shipment { PortOfOrigin = "USLOS", PortOfDestionation = "UKLON", 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 3000}, 
      new Invoice{InvoicePeriod = "201107", Amount = 2000} 
     } 
    }, 
    new Shipment { PortOfOrigin = "USDAL", PortOfDestionation = "UKLON", 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 3000} 
     } 
    } 
}; 

現在我想自由以下:

Shipment.PortOfOrigin,Shipment.PortOfDestionation,Shipment.Invoices.InvoicePeriod。

所以,我想這樣的

PortOfOrigin PortOfDestination InvoicePeriod Amount 
------------------------------------------------------------------------ 
USLOS   UKLON    201106   6000 
USLOS   UKLON    201107   3000 
USDAL   UKLON    201106   3000 

結果是這樣的,甚至可以做到一組這樣的,我想組在Invoices.InvoicePeriod?

+0

對於示例數據和所需結果的示例+1。很難得到一個清晰明確的問題:-) –

+0

謝謝你。 –

回答

1

更新:我已經更新了我的答案,包括髮貨數量。這要求貨件有一個ID字段。


下面將做的伎倆:

//first flatten the data so it's easier to manipulate 
var query = from s in shipments 
      from i in s.Invoices 
      select new 
      { 
       s.ShipmentUniqueIdentifier, 
       s.PortOfOrigin, 
       s.PortOfDestination, 
       i.InvoicePeriod, 
       i.Amount 
      }; 

//group the data as desired 
var grouping = query.GroupBy(q => new { q.PortOfOrigin, q.PortOfDestination, q.InvoicePeriod }); 

//finally sum the amounts 
var results = from g in grouping 
       select new 
       { 
        g.Key.PortOfOrigin, 
        g.Key.PortOfDestination, 
        g.Key.InvoicePeriod, 
        Amount = g.Select(s => s.Amount).Sum(), 
        NumberOfShipments = g.Select(s => s.ShipmentUniqueIdentifier).Distinct().Count() 
       }; 

下面是輸出:

enter image description here

UPDATE:正如所承諾的,這裏有一個完整的工作示例:

public class Shipment { 
    public Guid ShipmentUniqueIdentifier{get;set;} 
    public string PortOfOrigin{get;set;} 
    public string PortOfDestination{get;set;} 
    public ICollection<Invoice> Invoices{get;set;} 
} 

public class Invoice { 
    public string InvoicePeriod {get;set;} 
    public decimal Amount {get;set;} 
} 

List<Shipment> shipments = new List<Shipment> 
{ 
    new Shipment { PortOfOrigin = "USLOS", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(), 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 1000}, 
      new Invoice{InvoicePeriod = "201106", Amount = 2000}, 
      new Invoice{InvoicePeriod = "201107", Amount = 1000} 
     } 
    }, 
    new Shipment { PortOfOrigin = "USLOS", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(), 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 3000}, 
      new Invoice{InvoicePeriod = "201107", Amount = 2000} 
     } 
    }, 
    new Shipment { PortOfOrigin = "USDAL", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(), 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 3000} 
     } 
    } 
}; 

void Main() 
{ 
    //first flatten the data so it's easier to manipulate 
    var query = from s in shipments 
       from i in s.Invoices 
       select new 
       { 
        s.ShipmentUniqueIdentifier, 
        s.PortOfOrigin, 
        s.PortOfDestination, 
        i.InvoicePeriod, 
        i.Amount 
       }; 

    //group the data as desired 
    var grouping = query.GroupBy(q => new { q.PortOfOrigin, q.PortOfDestination, q.InvoicePeriod }); 

    //finally sum the amounts 
    var results = from g in grouping 
        select new 
        { 
         g.Key.PortOfOrigin, 
         g.Key.PortOfDestination, 
         g.Key.InvoicePeriod, 
         Amount = g.Select(s => s.Amount).Sum(), 
         NumberOfShipments = g.Select(s => s.ShipmentUniqueIdentifier).Distinct().Count() 
        }; 

    //output the results 
    results.Dump(); 
} 
+0

謝謝。是的,我想過提供數據,但我想我需要創建一個新類來做到這一點,但如果我使用第一個linq語句,我不必這樣做。 –

+0

有沒有一種方法可以獲得這裏包含的正確數量的發貨。如果我只將g.Count()添加到它,那麼我將得到與每個組的發票相同的數字(因爲它是平坦的)。那麼我怎樣才能得到這個例子上面的貨物數量應該是:2,2和1.而不是3,2和1 –

+0

@Magnus我已經更新了我的答案以給出發貨數量(upvote會是一個不錯的獎勵;-)) –