林奇无用的清单

时间:2016-03-25 16:21:21

标签: c# linq

以下代码生成两个项目。第一项包含Component个对象的列表。第二个项目还包含Component个对象的列表。在此示例中,第二个列表应为空,因为Component列表没有DishID=10。我该如何解决这个问题?

换句话说,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; }
    }
}

2 个答案:

答案 0 :(得分:2)

如果ComponentId为空(在本例中为0),则没有匹配项,因此在创建结果列表项时过滤空Component个对象,在本例中使用.Where (x => x.ComponentID > 0)在最后一个select语句之前:

        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)为空。

如果我理解你的要求,我认为代码可以简化:

  • 遍历每个Dish项目
  • 从当前所选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 LINQfrom 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的{​​{1}}项。

答案 1 :(得分:1)

老实说,我不明白为什么你使用所有左连接,分组和中间投影(选择),而你可以通过这样的简单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();