我有三个表(“评级”,“评论”和“用户”)。一个评级可以有多个评论。一条评论属于一个用户。
到目前为止,我有这个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);
我该如何分组?
答案 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:只是旁注:表格应以单数形式命名。在这种情况下,Rating
,Comment
和User
代替Ratings
,Comments
和Users
。
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() };