2015-03-31 105 views
0

我有以下兩個類;使用基於子項目的Lambda/Linq篩選器父集合

public class Order 
{ 
    public int Id {get;set;} 
    public List<Item> Items {get;set;} 
    public DateTime CreatedOn {get;set;} 
} 

public class Item 
{ 
    public int Code {get;set;} 
    public int SupplierId {get;set;} 
    public string Name {get;set;} 
    public decimal Price {get;set;} 
} 

我有訂單清單,每個訂單包含許多不同的項目。我想篩選訂單清單,以便我可以實現以下目標;

  • 返回所有訂單,其中項目列表中至少1項有供應商ID = 1
  • 不返回任何訂單,如果沒有項目匹配供應商ID = 1

UPDATE

如何擴展結果以便我只返回訂單和具有SupplierId = 1的項目

這是wh在我嘗試到目前爲止,現在工作。但我怎樣才能進一步壓縮它;

List<Order> OrderList = new List<Order>(); 

foreach(Order order in Order.Get(1)) 
{ 
    Order tmpOrder = order; 
    tmpOrder.Items = order.Items.Where(x => x.SupplierId == 1).ToList(); 

    if (tmpOrder.Items.Count > 0) 
     OrderList.Add(tmpOrder); 
    } 
+1

到目前爲止您嘗試過哪些方面,以及您嘗試解決方案時遇到了哪些問題?您的需求中的每一步都幾乎準確地逐個映射到LINQ操作。 – Servy 2015-03-31 15:48:30

回答

5

返回所有訂單,其中項目列表中至少1項有供應商ID = 1

不返回任何訂單,如果沒有項目匹配供應商ID = 1

IEnuemrable<Order> orders = //... 

var supplierOrders = orders.where(o => o.Items.Any(i => i.SupplierId == 1)) 
    .ToList(); 

看起來很直截了當。除非你的意思是返回所有的訂單,如果任何順序有1

更新一個供應商ID 1

如何展開的結果,這樣我只返回訂單和項目有供應商ID = 1

EF目前(據我所知EF6)不允許您在單個查詢中執行此操作。考慮到EF面臨的Cartesian Product問題(有時),它仍然非常容易並且實際上是高性能的。

public class MyDbContext : DbContext 
{ 
    DbSet<Order> Order { get; set; } 
    DbSet<Item> Items { get; set; } 
| 

// each of these orders do not contain any 
// items, we did not .Include() them. 
var supplierOrders = db.Orders 
    .Where(o => o.Items 
       .Any(i => i.SupplierId == 1)) 
    .ToList(); 

var orderIds = supplierOrders 
    .Select(so => so.Id) 
    .ToList(); 

var supplierItems = db.Items. 
    .Where(i => orderIds.Contain(i.SupplierId)) 
    .ToList(); 

因爲我們使用EF語境下,它會自動將,只要你有EF正確的關係設置(我建議做)線了任何項目的聯繫人緩存在本地任何相關的項目。

+0

只想返回包含Supplierid = 1的項目的訂單。 – Tommassiov 2015-03-31 16:05:30

+0

這正是這樣做的。 – 2015-03-31 16:34:12

+0

或者你的意思是你想要的訂單包含帶有SupplierId的項目,並且只有帶有SupplierId = 1的項目。 – 2015-03-31 16:34:49