使用LINQ从模型中获取父级名称和子项数量

3

我有以下模型:

public Class Category{
   public int Id {get;set;}
   public string Name {get;set;}
   public ICollection<SubCategory> SubCategories {get;set;}
}

public Class SubCategory{
   public int Id {get;set;}
   public string Name {get;set;}
   public int CategoryId { get; set; }
   public virtual Category Category{ get; set; }
   public ICollection<Ticket> Tickets { get; set; }
}

public class Ticket {
    public Ticket();

    public int Id { get; set; }
    public virtual SubCategory SubCategory{ get; set; }
    public int SubCategoryId{ get; set; }   
}

我想通过以下查询按类别分组获取数据,并获得每个子类别中票的数量:
Entities
                .Include(h => h.SubCategories )
                .ThenInclude(s => s.Tickets)
                .GroupBy(s => s.Id)
                .Select(t => new Cata {
                    Name = t.FirstOrDefault().Name,
                    Children = GetChildern(t.FirstOrDefault().SubCategories )
                });



public List<SubCat> GetChildern(IEnumerable<SubCategories> subs)
        {
            var output = new List<SubCat>();
            foreach (var sub in subs) {
                var subcat = new SubCat();
                subcat.Name = sub.Name;
                if (sub.Tickets != null) {
                    subcat.Size = sub.Tickets.Count;
                }
                output.Add(subcat);
            }
            return output;
        }

使用上述查询,所有票的数量始终为零,但实际上存在票。


3
显然,您的查询正落入“被忽略的包含”类别。不要无需使用GroupBy,并避免使用导致客户端评估的自定义方法。 - Ivan Stoev
2个回答

2

如果您的查询从类别开始,我不明白为什么需要进行分组。

var result=  Entities
            .Include(h => h.TicketSubCategories)
            .ThenInclude(s => s.Tickets)
            .Select(t => new Cata {
                            Name = t.Name,
                            Children= t.TicketSubCategories
                                       .Select(ts=>new SubCat{
                                                     Name=ts.Name,
                                                     Count=ts.Tickets.Count()})
                         };

我同意@Ivan的评论,这里不需要使用自定义方法,如果使用它,你将强制查询的投影在客户端上执行而不是在服务器(你的数据库)上执行。


在阅读了您的更新后,我现在明白您期望的输出是什么了,请看一下我的第二个查询。 - ocuenca

0

因此,每个类别都有零个或多个子类别,每个子类别都有零个或多个工单。每个工单属于恰好一个子类别,每个子类别属于恰好一个类别。

你想要一个查询,得到具有相同类别的子类别组。你想要每个子类别的某些(或所有)属性,但最重要的是,你想要每个子类别拥有的工单数量。

每个子类别组中的所有元素都属于同一类别。你还想要这个类别的一些(如果不是全部)属性。

解决方案是将所有子类别分组为具有相同类别的组(为了效率使用CategoryId)。然后使用Select获取所需属性。

var result = SubCategories 
    // group them into groups with same CategoryId
    .GroupBy(subCategory => subCategory.CategoryId
    // from every group take the properties you want: 
    .Select(group => new
    {
        // All SubCategories in one group belong to the same Category.
        // For efficiency, take only the Category properties you plan to use,
        CommonCategory = group.Key.Select(category => new
        {
            // take the category properties you want to use
        }

        // The group has a lot of SubCategories.
        // For each subcategory select only the properties you want to use
        SubCategories = group.Select(subCategory => new
        {
            // one of the properties you want is the number of Tickets of this SubCategory:
            TicketCount = subCategory.Tickets.Count(),

            // for efficiency: select only SubCategory properties you plan to use:
            Property1 = subCategory.Property1,
            Property2 = subCategory.Property2,
            ...
        }),
    });

因此,结果是一系列对象。每个对象都有两个属性:

  • SubCategories:属于同一类别的所有SubCategories的一些属性的序列。
  • CommonCategory:所有SubCategories所属的类别的几个属性。

SubCategories是一个序列。序列的每个元素都是一个带有多个属性的对象:

  • TicketCount:SubCategory中票数的数量
  • 其他属性:SubCategory的其他几个属性

从这里可以很容易地构建代码来获取子项


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接