我有一个实体框架查询,我在那里计算一些学生的成绩。查询如下:
(
from s in Students.Where(a => a.GroupId == groupId)
from q in Quizzes.Where(a => a.GroupId == groupId)
from qa in QuizAnswers.Where(a => a.UserId == s.UserId && a.QuizId == q.QuizId).DefaultIfEmpty()
select new Response
{
UserId = s.UserId,
UserFullName = s.FullName,
ActivityType = "Quiz",
ActivityId = q.QuizId,
ActivityName = q.Name,
DueDate = q.DueDate,
Score = qa == null ? null : qa.Score,
MaxScore = qa != null ? qa.MaxScore ?? 0 : 0,
IsSent = qa != null && qa.DateSent != null,
}
)
.OrderBy(a => a.DueDate).ThenBy(a => a.ActivityId)
.AsEnumerable()
.GroupBy(a => new User
{
a.UserId,
a.UserFullName,
})
此查询加入所有学生和所有测验。我没有直接查询QuizAnswers,因为如果学生没有打开测验,它还不存在,但我需要一个占位符来显示在报告卡上。
现在,当我在LinqPad上运行它时,查询正常工作。在我正在进行的示例中,它显示了4个测验和700个学生,并且所有条目都被正确检索。
但是,在应用程序(它是一个ASP.NET MVC 4应用程序)上放置相同的查询,在迭代查询时,它会显示所有700名学生,但只显示第一个测验。我也试过添加和删除测验,但它总是只显示第一个。
由于LinqPad正确运行查询,是否有任何实体框架或ASP.NET MVC采取不同的做法?可能是优化,还是配置还是什么?
答案 0 :(得分:1)
问题是我在LinqPad和Visual Studio中都没有运行完全相同的查询。
在LinqPad中,我有GroupBy(a => new { /* stuff */ })
,而在Visual Studio中我有GroupBy(a => new User { /* stuff */ })
,其中User
是不属于实体框架的类。
正如我后来发现的那样,GroupBy
需要一个具有重写等式的类,匿名类具有该类,但我的自定义类没有。
解决方案是覆盖Equals
定义中的User
。
答案 1 :(得分:0)
在VS GroupBy
中应为Type
稍微改变查询的顺序。
改为:
from tt in ( from s in Folder.Where(a => a.GroupId == groupId)
from q in Quizzes.Where(a => a.GroupId == groupId)
from qa in QuizAnswers.Where(a => a.UserId == s.UserId && a.QuizId == q.QuizId).DefaultIfEmpty()
)
group tt by new {a.UserId, a.UserFullName}
into grp
select new
{
UserId = grp.tt.UserId,
UserFullName = grp.tt.FullName,
ActivityType = "Quiz",
ActivityId = grp.tt.QuizId,
ActivityName = grp.tt.Name,
DueDate = grp.tt.DueDate,
Score = grp.tt == null ? null : grp.tt.Score,
MaxScore = grp.tt != null ? grp.tt.MaxScore ?? 0 : 0,
IsSent = grp.tt != null && grp.tt.DateSent != null,
}
)
.OrderBy(a => a.DueDate).ThenBy(a => a.ActivityId)
.AsEnumerable()