2016-03-25 26 views
-2

以下代碼會產生兩個項目。第一個項目包含一個Component對象的列表。第二個項目還包含一個Component對象的列表。在這個例子中,第二個列表應該是空的,因爲Component列表沒有DishID=10。我該如何解決這個問題?Linq無用列表

換句話說result[1].components.Count應該是0。

namespace ConsoleApplication3 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Component> Component = new List<Component>(); 
      List<Dish> Dish = new List<Dish>(); 
      Dish.Add(new Dish { DishID = 9, CategoryID = 6, DishName = "Pork" }); 
      Dish.Add(new Dish { DishID = 10, CategoryID = 6, DishName = "Beef" }); 
      Component.Add(new Component { ComponentID = 1, DishID = 9, AmountID = "1", NameID = "1" }); 

      List<Item> result = (from dishes in Dish 
           join components in Component on dishes.DishID equals components.DishID 
            into item 
           from p in item.DefaultIfEmpty() 
           select new { CategoryID = dishes.CategoryID, DishID = dishes.DishID, ComponentID = p != null ? p.ComponentID : default(int), DishName = dishes.DishName, AmountID = p != null ? p.AmountID : null, NameID = p != null ? p.NameID : null }).ToList().GroupBy(key => key.DishID) 
            .Select(g => new Item() 
            { 
             DishID = g.Key, 
             components = g.Select(t => new Component { AmountID = t.AmountID, ComponentID = t.ComponentID, DishID = t.DishID, NameID = t.NameID }).ToList() 
            }) 
             .ToList(); 
     } 
    } 
    public class Item 
    { 
     public int DishID { get; set; } 

     public List<Component> components { get; set; } 
    } 

    public partial class Component 
    { 
     public int ComponentID { get; set; } 
     public int DishID { get; set; } 
     public string AmountID { get; set; } 
     public string NameID { get; set; } 
    } 

    public partial class Dish 
    { 
     public int DishID { get; set; } 
     public int CategoryID { get; set; } 
     public string DishName { get; set; } 
    } 
} 
+0

爲什麼downvoted? – A191919

回答

2

如果COMPONENTID是空的(在這種情況下0),不存在匹配,因此創建的結果列表中的項時過濾空Component目的,在這種情況下,最後一個SELECT語句前使用.Where (x => x.ComponentID > 0)

 List<Item> result = (from dishes in Dish 
          join components in Component on dishes.DishID equals components.DishID into item 
          from p in item.DefaultIfEmpty() 
          select new 
           { 
            CategoryID = dishes.CategoryID, 
            DishID = dishes.DishID, 
            ComponentID = p != null ? p.ComponentID : default(int), 
            DishName = dishes.DishName, 
            AmountID = p != null ? p.AmountID : null, 
            NameID = p != null ? p.NameID : null 
           }) 
           .ToList() 
           .GroupBy(key => key.DishID) 
           .Select(g => new Item() 
           { 
            DishID = g.Key, 
            components = g 
               .Where (x => x.ComponentID > 0) 
               .Select(t => new Component 
                   { 
                    AmountID = t.AmountID, 
                    ComponentID = t.ComponentID, 
                    DishID = t.DishID, 
                    NameID = t.NameID 
                   }) 
                .ToList() 
           }) 
           .ToList(); 

現在的結果包含兩個項目,第一個具有DishId=9和第二列表(DishId=10)爲空。

如果我正確理解你的要求,我覺得代碼可以簡化爲:

  • 迭代在每一道菜項目從當前所選DishId組件列表
  • 選擇項目:如果沒有匹配,該列表將是空

的代碼看起來是這樣的:

 List<Item> result1 = new List<Item>(); 
     Dish.ForEach(dish => 
     { 
      var item = new Item 
      { 
       DishID = dish.DishID, 
       components = Component.Where (c => c.DishID == dish.DishID).ToList() 
      }; 
      result1.Add(item); 
     }); 

輸出與您的代碼相同。


因爲你是一個LEFT JOIN using LINQ(與from p in item.DefaultIfEmpty()),我想你也想排除的結果的空項。這可以通過添加一個where條件(where ((p != null) && (p.ComponentID > 0)))的第一個查詢來完成:

 List<Item> result = (from dishes in Dish 
          join components in Component on dishes.DishID equals components.DishID into item 
          from p in item.DefaultIfEmpty() 
          where ((p != null) && (p.ComponentID > 0)) 
          select new 
           { 
            CategoryID = dishes.CategoryID, 
            DishID = dishes.DishID, 
            ComponentID = p != null ? p.ComponentID : default(int), 
            DishName = dishes.DishName, 
            AmountID = p != null ? p.AmountID : null, 
            NameID = p != null ? p.NameID : null 
           }) 
           .ToList() 
           .GroupBy(key => key.DishID) 
           .Select(g => new Item() 
           { 
            DishID = g.Key, 
            components = g.Select(t => new Component 
                   { 
                    AmountID = t.AmountID, 
                    ComponentID = t.ComponentID, 
                    DishID = t.DishID, 
                    NameID = t.NameID 
                   }) 
                .ToList() 
           }) 
           .ToList(); 

結果包括,如預期,僅Component項目的DishId=9

+0

我可能會困惑你。但結果應該包含兩個itens DishID = 9(包含具有1個項目的列表組件),DishID = 10(包含列表組件和0個項目)。 – A191919

+0

我修改了我的答案中的代碼以匹配此條件。 – pasty

+0

我用另一種代碼解決方案增強了我的答案。 – pasty

1

老實說,我不明白爲什麼你用所有的左聯接,GROUP BY和中間突起(選擇),而可以實現用一個簡單的Group Join這樣期望的結果:

var result = (
    from d in Dish 
    join c in Component on d.DishID equals c.DishID into items 
    select new Item { DishID = d.DishID, components = items.ToList() } 
    ).ToList();