如果您希望了解的有关评级的所有信息都是汇总信息(总和、平均值、计数等),那么您可以执行以下操作:
var profiles = from userprof in Ent.UserProfiles
join userrating in Ent.UserRatings on userprofs.UserId equals userratings.UserId
where userrating.DateAdded >= drm.Start
group userrating by userprof into g
select new {g.Key.UserID, g.Key.UserName, Count = g.Count(), Avg = g.Avg(r => r.RatingValue) };
请注意,我将复数名称更改为单数名称,因为我们根据每个单独的项目定义 linq 查询(UserProfiles 是复数,而 userprof 每个项目都“在”其中)。
这可以很好地直接转换为 SQL:
SELECT up.userID, up.userName, COUNT(ur.*), AVG(ur.ratingValue)
FROM UserProfiles up JOIN UserRatings ur
ON up.userID = ur.userID
WHERE dateAdded > {whatever drm.Start is}
GROUP BY up.userID, up.userName
如果我们希望能够获得单独的评级,这与单个 SQL 查询不太匹配,我们可以这样做:
var profiles = from userprof in Ent.UserProfiles
join userrating in Ent.UserRatings on userprofs.UserId equals userratings.UserId
where userrating.DateAdded >= drm.Start
group new{userrating.RatingValue, userrating.SomeThing} by new{userprof.UserID, userprof.UserName};
这将为我们提供一个IEnumerable<Grouping<{anonymous object}, {anonymous object}>>
我们可以迭代的对象,在每次迭代中获得一个新的Key.UserID
and Key.UserName
,并能够依次迭代得到item.RatingValue
and item.SomeThing
(我添加用于演示,如果我们只想要它的值IEnumerable<Grouping<{anonymous object}, int>>
)就像这个:
foreach(var group in profiles)
{
Console.WriteLine("The user is :" + group.Key.UserName + " (id: " + group.Key.UserID ")");
foreach(var item in group)
{
Console.WriteLine(item.SomeThing + " was rated " + item.RatingValue);
}
}
然而,这个问题是没有一个很好的单个 SQL 查询可以映射到。Linq 会尽力而为,但这意味着要执行几个查询,所以你最好帮助它:
var profiles = from item in (from userprof in Ent.UserProfiles
join userrating in Ent.UserRatings on userprofs.UserId equals userratings.UserId
where userrating.DateAdded >= drm.Start
select new{userrating.RatingValue, userrating.SomeThing, userprof.UserID, userprof.UserName}).AsEnumerable()
group new{item.RatingValue, item.SomeThing} by new{item.UserID, item.UserName}
这与以前的输出相同,但转换为 SQL 允许进行单个查询,其余工作在内存中完成。99% 的情况下,像这样将一些工作拖到内存中会降低效率,但是因为之前没有可以映射到的单个 SQL 查询,所以这是一个例外。