如何使用Linq对两个以上的表进行分组

时间:2015-09-26 12:07:43

标签: c# linq multiple-tables linq-group

我有三个表(“评级”,“评论”和“用户”)。一个评级可以有多个评论。一条评论属于一个用户。

到目前为止,我有这个LINQ语句正常工作。

from rating in Ratings
join comment in Comments
on rating.ID equals comment.RatingID
join user in Users
on comment.UserID equals user.ID
select new {rating, comment, user}
.Where(x => x.rating.LocationID == 3);

我该如何分组?

1 个答案:

答案 0 :(得分:3)

这取决于你想要分组的内容。但有多种解决方案。

解决方案1:

假设您想按评分进行分组,那么您可以这样做:

var query1 = from rating in db.Ratings
                join comment in db.Comments
                    on rating.ID equals comment.RatingID
                join user in db.Users
                    on comment.UserID equals user.ID
                group new { comment, user } by rating into g
                select new { g.Key, l = g.ToList() };

foreach (var row in query1)
{
    // you get rows grouped by rating
    Debug.WriteLine(row.Key.ID); // rating.ID

    // and a list of comments/users per rating
    foreach (var g in row.l)
    {
        Debug.WriteLine(g.comment.ID);
        Debug.WriteLine(g.user.ID);
    }
}

这为每个评级提供了一条线。动态对象g包含每个评级的评论/用户对列表。

解决方案2:

但是,就像@gertarnold提到的那样,只需读入要分组的对象就更容易了。然后遍历它的属性。像这样:

var query2 = db.Ratings;

foreach (var rating in query2)
{
    Debug.WriteLine(rating.name);
    foreach (var comment in rating.Comments)
    {
        Debug.WriteLine(comment.name);
        Debug.WriteLine(comment.User.name);
    }
}

这更易于理解。它的性能下降很难,因为它为内部循环中的每个注释执行单独的数据库SELECT - 语句。如果评级有很多评论,那么这很慢。分组的第一个示例将单个数据库SELECT语句中的所有内容拉入,这要快得多。

解决方案3:

并且有一种方法可以充分利用这两种解决方案。在解决方案2中执行此操作并在其前面添加一些DataLoadOptions

DataLoadOptions options = new DataLoadOptions();
options.LoadWith<Rating>(rating => rating.Comments);
options.LoadWith<Comment>(comment => comment.User);
db.LoadOptions = options;

这将使用单个SELECT中的所有必需子对象预加载所有评级。它快速,易于阅读和理解。

PS:只是旁注:表格应以单数形式命名。在这种情况下,RatingCommentUser代替RatingsCommentsUsers

PS2:要在解决方案1中获得没有注释的评级,您需要将连接转换为外连接。像这样:

var query1 = from rating in db.Ratings
        join comment in db.Comments
            on rating.ID equals comment.RatingID into j1
        from comment in j1.DefaultIfEmpty()
        join user in db.Users
            on comment.UserID equals user.ID into j2
        from user in j2.DefaultIfEmpty()                                
        group new { comment, user } by rating into g
        select new { g.Key, l = g.ToList() };

另见:101 LINQ Samples - Left outer join