LINQ To Entities INNER JOIN with COUNT

LINQ To Entities INNER JOIN with COUNT

我正在尝试使用理解方法在 LINQ 中复制以下查询。我的SQL如下:

SELECT COUNT(Post.Id), User.Id, User.Name
FROM Post  
INNER JOIN User ON Post.ModeratorId = User.Id
WHERE Post.Status IN ("Live", "Pending", "Expired")
GROUP BY User.Id, User.Name

我的 LINQ 查询如下,但是当没有为 post 分配主持人时,它仍然是 returns 0 计数。请注意 Post.ModeratorId 是一个可以为 null 的值。

我只想要一个版主列表和 post 他们正在或已经主持的计数。 如何在 LINQ 中复制上述 SQL?

    public IEnumerable<ModeratorPostViewModel> GetModeratorPostCount()
    {
        var posts = _context.Post
                       .Include(p => p.Moderator)
                       .Include(p => p.Status)
                       .Where(p => p.ModeratorId != null && p.Status.Name IN ("Live", "Pending", "Expired"))
                       .OrderBy(p => p.Moderator.Name)
                       .Select(p => new ModeratorPostViewModel 
                       {
                           Id = p.ModeratorId,
                           Name = p.Moderator.Name,
                           CountOfPosts = p.Moderator.ModeratorPosts.Count()
                       })
                       .ToList();

        // Return list
        return posts 
    }

我的模型定义如下:

public class Post
{
   int Id { get; set; }
   int StatusId { get; set; }
   string ModeratorId { get; set; }

   // Navigation properties
   public Status Status { get; set; }
   public ApplicationUser Moderator { get; set; }

   // some other other properties
}

public class ApplicationUser : IdentityUser
{
    public string Name { get; set; }

    // Navigation property
    public ICollection<Post> ModeratorPosts { get; set; }

}

I only want a list of moderators and a count of post they are or have moderated

然后将您的查询基于 Moderator(或任何名称)实体:

var statuses = new [] { "Live", "Pending", "Expired" };
var posts = _context.Moderator
    .OrderBy(m => m.Name)
    .Select(m => new ModeratorPostViewModel 
    {
        Id = m.Id,
        Name = m.Name,
        CountOfPosts = m.ModeratorPosts.Count(p => statuses.Contains(p.Status.Name))
    })
    .Where(m => m.CountOfPosts != 0)
    .ToList();

更新: 我不得不承认上面的 LINQ 查询并没有产生很好的 SQL,尤其是在最后一个 Where 条件下。因此,您可能会求助于 SQL 查询的确切 LINQ 等价物(您错过了 GROUP BY 部分):

var statuses = new [] { "Live", "Pending", "Expired" };
var posts = _context.Post
    .Where(p => p.ModeratorId != null && statuses.Contains(p.Status.Name))
    .GroupBy(p => new { Id = p.ModeratorId, Name = p.Moderator.Name })
    .Select(g => new ModeratorPostViewModel 
    {
        Id = g.Key.Id,
        Name = g.Key.Name,
        CountOfPosts = g.Count()
    })
    .OrderBy(m => m.Name)
    .ToList();

您可以在按您要查找的状态过滤帖子后进行分组

var s = new List<string>() {"Live", "Pending", "Expired"};
var grouped = db.Post.Where(x => s.Contains(x.Status)) //Fitler for the statuses
                 .GroupBy(f => f.ModeratorId, po => po,
                              (k, items) => new ModeratorPostViewModel
                                            {
                                               Name = items.FirstOrDefault().User.Name,
                                               Id=k, 
                                               CountOfPosts = items.Count()
                                            }).ToList();