LINQ左外连接通过扩展方法按组计数

时间:2017-08-18 06:27:13

标签: c# .net entity-framework linq

我有两张桌子。 CategoriesAds

每个CategoryAds表格中都有很多广告。

我想要所有类别的详细信息,包括每个广告的广告数量。

以下是我的Linq表达式,它仅提取包含广告的类别可能会导致FirstOrDefault()

我想知道如何实现结果,因为条件加上只有具有位置ID的类别(比方说:lid)" 7"。

在我的表达中

var x1 = context.Categories
                .GroupJoin(
                    context.ads,
                    cat => cat.id,
                    ad => ad.catid,
                    (cat, ad) => new { cats = cat, ads = ad })
                .SelectMany(
                    a => a.ads.DefaultIfEmpty(),
                    (a, y) => new { catss = a.cats, adss = y })
                .GroupBy(w => w.adss,ww=>new {  cat=ww.catss,count=ww.catss.ads.Count()})
                .Where(s=>s.FirstOrDefault().cat.lid==7);

2 个答案:

答案 0 :(得分:3)

显然CategoriesAds之间存在一对多的关系:每个Category都有零个或多个Ads,每个Ad属于只有一个Category

在适当的实体框架中,这将建模如下:

class Category
{
    public int Id {get; set;}
    // every Category has zero or more Adds:
    public virtual ICollection<Ad> Ads {get; set;}
    ...
}

class Ad
{
    public int Id {get; set;}
    // every Ad belongs to exactly one Category, using foreign key CategoryId:
    public int CategoryId {get; set;}
    public Category Category {get; set;}
    ...
}

如果您的类是这样建模的,实体框架将假定Category和Add之间的正确的一对多关系。可能是您对某些属性有不同的名称,并且您使用了Attributes和/或Fluent API,但类的结构将类似。

完成此操作后,您的查询比您想象的更容易:

var result = dbContext.Categories.Select(category => new
{
    Category = Category,
    AdCount = Category.Adds.Count(),
};

单词:对于类别集合中的每个类别,创建一个具有两个属性的匿名类的新对象:

  • 类别包含所考虑的类别
  • AdCount包含该类别所拥有的广告数量。

实体框架的模型将理解为此需要连接和计数。

答案 1 :(得分:2)

您可以尝试以下内容:

var result = context.Categories
                    .Where(category => category.lid == 7)
                    .GroupJoin(
                        context.ads
                        , category => category.id
                        , ad => ad.catid
                        , (c,a) => new 
                        { 
                            Category = category, 
                            NumberOfAds = a.DefaultIfEmpty().Count(x => x!=null)
                        });