LINQ到实体INNER JOIN与COUNT

时间:2016-07-20 20:11:52

标签: c# sql entity-framework linq linq-to-entities

我尝试使用理解方法在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查询如下所示,但是当没有为帖子分配主持人时,它仍然返回0计数。请注意,Post.ModeratorId是可以为空的值。

我只需要一个主持人列表以及他们已经或已经过审核的帖子数量。 如何在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; }

}

2 个答案:

答案 0 :(得分:3)

  

我只想要一份主持人名单和他们已经或已经过审核的职位数

然后将您的查询基于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();

答案 1 :(得分:0)

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

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();