在LINQ中复制SQL查询

时间:2011-03-22 10:17:18

标签: c# sql asp.net-mvc linq

我有一个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 App。 ASP视图“Progression”传递了varibale“groups”,它是一些选定组的列表。我目前正在使用以下代码,该代码非常慢(加载页面时间为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,然后对小组中的每个小组进行预约,所以大约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数据类型,但我希望它能够解决我在这里尝试做的事情。

我不确定我是否已经解释得非常好但是如果有人有任何想法我会非常感激,这已经困扰了我好几天了!

2 个答案:

答案 0 :(得分:2)

SQL的字面转换类似于:

from g in db.Groups
join e in db.Enrolments on g.CourseID equals e.GroupID
join s in db.Students in e.StudentID equals s.StudentID
join p in db.Progressions on s.StudentID equals p.StudentID  
where p.IsReturning == 0  
GROUP new {
   Group = g,
   Enrolment = e,
   Student = s,
   Progression = p
} by g.GroupID into grouped 
select new
{
   GroupId = grouped.Key,
   Returning = grouped.Count()
};

虽然g.CourseID equals e.GroupID看起来有点奇怪!


顺便说一句,如果您的最终目标是选择一个进度列表,那么我发现最简单的方法是使用Progressions作为首选项而不是组来启动查询。

答案 1 :(得分:2)

此LINQ查询将执行您在注释中表达的内容:

var groups =
    from g in db.Groups
    let returningStudents =
        from enrolment in g.Enrolments
        let student = enrolment.Student
        where student.Progressions.Any(p => p.IsReturning)
        select student
    select new GroupStudentReturnCountDto
    {
        Name = g.Name,
        StudentReturnCount = returningStudents.Count()
    };

这个查询非常有效,因为它允许数据库进行计数,并且只返回实际使用的数据。如果它仍然不够快,只需添加正确的数据库索引,你就完成了; - )