2011-03-22 35 views
1

我有一段ASP.NET MVC應用程序,我現在正在使用LINQ to SQL一段時間。我已經在LINQ中複製了大多數查詢,但是現在有一件事讓我陷入了困境。在LINQ中複製SQL查詢

我想選擇一個條件滿足的「進步」列表,並且我有一個組列表。

我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視圖「Progression」通過varibale「groups」,它是幾個選定組的列表。我目前使用的follwing代碼,這是很慢(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>  
     <% 
     } %> 

我指望一些其他的東西太多,但在這個例子中,我會堅持的。現在顯然這很慢,因爲它必須爲團體做一些事情,然後對於每個團隊中的每個人來說,所以大約有10個團隊,每個團隊中有20個學生。我deally我想要做這樣的事情,它消除了第二的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子句不返回布爾數據類型,但我希望得到什麼防空火炮我正試着在這裏做。

我不確定我是否已經解釋得很好,但如果有人有任何想法,我會非常感激,這已經讓我煩惱了好幾天!

+0

您可以定義要在界面中顯示的內容(以功能的方式)。這對我來說不是很清楚。 – Steven 2011-03-22 11:13:53

+0

基本上我只是試圖爲選定列表中的每個組創建一個表格,並且爲每個組計算勾選了「IsReturning」字段的學生人數。 因此,在僞代碼中:計數IsReturning = true的組中的學生。重複每組。 – Chris 2011-03-22 13:22:01

回答

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看起來有點怪!


順便說一句,如果你的最終目標是選擇級數的列表,然後我覺得最簡單的開始與級數查詢作爲被選中的第一件事情,而不是與組。

+0

謝謝,該代碼選擇我需要的。我現在遇到的問題是,它返回一個IEnumerable匿名類型,我無法傳遞給我的視圖(請參見[這裏](http://stackoverflow.com/questions/284637/iterating-through-anonymous-typed-data-in -mvc視圖))。我認爲easiet的方法將是在SQL Server數據庫中創建一個View,並將它作爲一個類導入到MVC應用程序中,這對於一個查詢來說是相當不整潔的! – Chris 2011-03-22 16:45:02

+0

另外,well spotted:g.CourseId是一個錯字它應該是g.groupID! – Chris 2011-03-22 16:48:32

+0

如果您不想創建視圖,請創建一個類...例如class SpecialResult {public Group Group {get; set;} public int Returning {get; set;}} - 然後你可以在查詢 – Stuart 2011-03-22 17:00:49

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() 
    }; 

這個查詢將是非常有效的,因爲它可以讓數據庫執行計數,並只返回被實際使用的數據。如果仍然不夠快,只需添加正確的數據庫索引,然後完成;-)

+0

中選擇這個新東西,謝謝這段代碼也做我需要的東西,速度很快,但是返回一個IEnumerable匿名類型,我不能傳遞給視圖(請參閱其他答案的評論) – Chris 2011-03-22 16:47:00

+1

不返回一個匿名類型比。創建一個自定義類型並返回它。不要創建數據庫視圖,這很愚蠢,很快就會成爲維護噩夢。 – Steven 2011-03-22 20:05:51