在 LINQ 中复制 SQL 查询
我有一个 ASP.NET MVC 应用程序,我已经将其与 LINQ to SQL 一起使用了一段时间。我已经掌握了在 LINQ 中复制大多数查询的窍门,但有一个查询已经让我难住了好几天了。
我正在尝试选择满足条件的“进度”列表,并且我有一个组列表。
我的ERD如下:
“组”1<->许多“注册”许多<->1“学生”1<->许多“进度”
标准 SQL 是(除了在代码中,我将一组特定的组传递给函数):
SELECT dbo.[Group].GroupID, COUNT(*) AS returning
FROM dbo.[Group] INNER JOIN
dbo.Enrolment ON dbo.[Group].CourseID = dbo.Enrolment.GroupID INNER JOIN
dbo.Student ON dbo.Enrolment.StudentID = dbo.Student.StudentID INNER JOIN
dbo.Progression ON dbo.Student.StudentID = dbo.Progression.StudentID
WHERE (dbo.Progression.IsReturning = 0)
GROUP BY dbo.[Group].GroupID
现在是 Web 应用程序。 ASP 视图“进度”传递变量“组”,它是几个选定组的列表。我目前正在使用以下代码,该代码非常慢(加载页面需要 30 秒或更长的时间),
<%foreach (var tg in Model)
{%>
<% notreturning = 0; %>
<%foreach (Enrolment e in tg.Enrolments)
{
notreturning = notreturning + e.Student.Progressions.Where(p => !p.IsReturning).Count();
}%>
<tr>
<td><% = notreturning %></td>
</tr>
<%
} %>
我也在计算其他一些内容,但在这个例子中我将坚持使用一个。现在显然这非常慢,因为它必须对组进行 foreach,然后对组中的每个注册进行 foreach,因此大约 10 个组乘以每个组 20 名学生。我确实想做类似以下的事情,消除第二个 foreach:
<%foreach (var tg in Model)
{%>
<% notreturning = 0; %>
<%var test = tg.Enrolments.Where(e => e.Student.Progressions.Where(p => !p.IsReturning)).Count(); %>
<tr>
<td><% = notreturning %></td>
</tr>
<%
} %>
该代码不起作用,因为嵌套的 where 子句不返回 bool 数据类型,但我希望它能完成我在这里尝试做的事情。
我不确定我是否解释得很好,但如果有人有任何想法,我将非常感激,这已经困扰我好几天了!
I have an ASP.NET MVC application which I have being using with LINQ to SQL for a while now. I have got the hang of replicating most queries in LINQ but there is one that has had me stumped for several days now.
I am trying to select a list of "Progressions" where a condition is met, and I have a list of groups.
My ERD is as follows:
"Group" 1<->Many "Enrolments" Many<->1 "Students" 1<->Many "Progressions"
And the standard SQL would be (Except in the code I have a specific set of groups passed to the function):
SELECT dbo.[Group].GroupID, COUNT(*) AS returning
FROM dbo.[Group] INNER JOIN
dbo.Enrolment ON dbo.[Group].CourseID = dbo.Enrolment.GroupID INNER JOIN
dbo.Student ON dbo.Enrolment.StudentID = dbo.Student.StudentID INNER JOIN
dbo.Progression ON dbo.Student.StudentID = dbo.Progression.StudentID
WHERE (dbo.Progression.IsReturning = 0)
GROUP BY dbo.[Group].GroupID
Now for the Web App. The ASP view "Progression" gets passed the varibale "groups" which is a list of a few selected groups. I am currently using the follwing code, which is very slow (30 secs or more to load page)
<%foreach (var tg in Model)
{%>
<% notreturning = 0; %>
<%foreach (Enrolment e in tg.Enrolments)
{
notreturning = notreturning + e.Student.Progressions.Where(p => !p.IsReturning).Count();
}%>
<tr>
<td><% = notreturning %></td>
</tr>
<%
} %>
I am counting some other stuff too but for this example I'll stick to one. Now obviously this is quite slow because it has to do a foreach for groups, then for each enrolment in the group, so around 10 groups times 20 students in each. I deally I want to do something like the following which eliminates the second foreach:
<%foreach (var tg in Model)
{%>
<% notreturning = 0; %>
<%var test = tg.Enrolments.Where(e => e.Student.Progressions.Where(p => !p.IsReturning)).Count(); %>
<tr>
<td><% = notreturning %></td>
</tr>
<%
} %>
That code doesn't work as the nested where clause doesn't return a bool data type, but I hope it get accross what I'm trying to do here.
I'm not sure if I've explained this very well but if anyone has any ideas I would be very grateful, this has been bugging me for days!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
SQL 的字面转换类似于:
虽然
g.CourseID equals e.GroupID
看起来有点奇怪!顺便说一句,如果您的最终目标是选择进度列表,那么我发现最简单的方法是使用进度作为第一个选择的内容而不是使用组来启动查询。
A literal conversion of your SQL is something like:
although
g.CourseID equals e.GroupID
looks a bit odd!As an aside, if your end goal is to select a list of Progressions, then I find it easiest to start the query with the Progressions as the first thing being selected rather than with the Groups.
此 LINQ 查询将执行您在注释中表达的操作:
此查询将非常高效,因为它让数据库进行计数,并且仅返回实际使用的数据。如果它仍然不够快,只需添加正确的数据库索引即可完成;-)
This LINQ query would do what you expressed in the comments:
This query would be very efficient, because it lets the database do the counting and it returns only the data that is actually used. If it still isn't fast enough, just add the right databases indexes and you're done ;-)