'EF get count from left join and joining on additional columns (Extension methods)

I am trying to do a simple query to get the count from joining two table but am having a really hard time trying to figure out this LINQ query.

I have two enitites:

public partial class BlogCategory
{
    public BlogCategory()
    {
        this.Blogs = new HashSet<Blog>();
    }

    public int BlogCategoryId { get; set; }
    public int SiteId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Blog> Blogs { get; set; }
    public virtual Site Site { get; set; }
}

public partial class Blog
{
    public int BlogId { get; set; }
    public int SiteId { get; set; }
    public int BlogCategoryId { get; set; }
    public bool IsDeleted { get; set; }

    public virtual BlogCategory BlogCategory { get; set; }
    public virtual Site Site { get; set; }
}

I am trying to get the count of blogs for each category like so in sql:

select bc.BlogCategoryId, bc.Name BlogCategoryName, count(b.BlogCategoryId) BlogCount from BlogCategory bc
left join Blog b on bc.BlogCategoryId = b.BlogCategoryId and b.IsDeleted = 0
where bc.SiteId = 1
group by bc.BlogCategoryId, bc.Name  

Converting this to EF extension methods has been a real pain. I am not sure how to write the where clause or if the group join is even correct. This is what I have so far:

var result = db.BlogCategories
    .GroupJoin(db.Blogs, bc => bc.BlogCategoryId, b => b.BlogCategoryId, (category, blogs) => new
    {
        Category = category,
        Blogs = blogs.DefaultIfEmpty()
    })
    .Where(bbc => bbc.Category.SiteId == siteId /*&& Check if blog IsDeleted? */)
    .Select(bbc => new BlogCategory
    {
        BlogCategoryId = bbc.Category.BlogCategoryId,
        Name = bbc.Category.Name,
        NumberOfBlogs = bbc.Blogs.Count()
    })
    .ToList();

Update:

I think I got it working but concerned about the SQL produced by EF:

result = db.BlogCategories
    .Where(bc => bc.SiteId == siteId)
    .GroupJoin(db.Blogs, bc => new { bc.BlogCategoryId, IsDeleted = false }, b => new { b.BlogCategoryId, b.IsDeleted }, (category, blogs) => new
    {
        Category = category,
        Blogs = blogs
    })
    .Select(bbc => new BlogCategory
    {
        BlogCategoryId = bbc.Category.BlogCategoryId,
        Name = bbc.Category.Name,
        NumberOfBlogs = bbc.Blogs.Count()
    })
    .ToList();

The SQL created:

exec sp_executesql N'SELECT 
    [Project2].[BlogCategoryId] AS [BlogCategoryId], 
    [Project2].[Name] AS [Name], 
    [Project2].[C1] AS [C1]
    FROM ( SELECT 
        [Project1].[BlogCategoryId] AS [BlogCategoryId], 
        [Project1].[Name] AS [Name], 
        (SELECT 
            COUNT(1) AS [A1]
            FROM [dbo].[Blog] AS [Extent2]
            WHERE ([Project1].[BlogCategoryId] = [Extent2].[BlogCategoryId]) AND (0 = [Extent2].[IsDeleted])) AS [C1]
        FROM ( SELECT 
            [Extent1].[BlogCategoryId] AS [BlogCategoryId], 
            [Extent1].[Name] AS [Name]
            FROM [dbo].[BlogCategory] AS [Extent1]
            WHERE [Extent1].[SiteId] = @p__linq__0
        )  AS [Project1]
    )  AS [Project2]',N'@p__linq__0 int',@p__linq__0=1

Can EF not create left joins similar to the sql outlined below? Not quite sure what is happening here. Seems like my EF query is missing something. Why are there 2 selects. One to get the Blog Categories and another to get blog counts. Is this efficient?

Why can EF create something similar to this?

select bc.BlogCategoryId, bc.Name BlogCategoryName, count(b.BlogCategoryId) BlogCount from BlogCategory bc
left join Blog b on bc.BlogCategoryId = b.BlogCategoryId and b.IsDeleted = 0
where bc.SiteId = 1
group by bc.BlogCategoryId, bc.Name  


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source