2014-10-19 150 views
1

我正在構建搜索邏輯(對於MVC應用程序)並簡單地說 - 我卡住了!Linq到具有多個相關實體性能和聯合的實體

我花了幾天建立Linq to Entities查詢來使用投影。在我查看下面生成的SQL語句之前,所有內容都表現良好。喘氣!

我接下來花了幾天的時間嘗試從SQL語句中刪除這些UNION語句,嘗試JOINs,FROMs,INCLUDE,任何只會給加載相關實體的內部/外部外部連接。

但是我還沒有能夠成功地做到這一點,仍然停留在這一點上。

幾點考慮:

  • L2E查詢包含與投影多個相關(子)實體(在這裏沒有問題,除非這是一個不好的設計,即,使工會)
  • 適合創建總結類匿名類型,例如學生摘要
  • 由於性能原因,彙總類只包含實體對象列的幾列 - 不需要在初始搜索時返回所有列
  • 最近開始使用PredicateBuilder從搜索返回學生,例如,具有專業化的男學生...在這方面都很好(迄今爲止)。

這是我到目前爲止已經完成(代碼改爲隱藏自有房產的物業 - 可能有錯別字):

query = from s in context.Students 
    select new StudentSummary 
    { 
     StudentID = s.StudentID, 
     Title = s.Title, 
     FullName = s.FullName, 
     Qualifications = s.Qualifications, 
     Gender = s.Gender, 
     CampusSummaries = (
        from c in s.Campuses 
        select new CampusSummary 
        { 
         Name = c.Name, 
         LocationSummary = new LocationSummary 
         { 
          State = c.Location.State 
         } 
        }), 
        SpecializationSummaries = (
            from sp in s.StudentSpecializations 
            select new StudentSpecializationSummary 
             { 
              StudentSpecializationID = sp.StudentSpecializationID, 
              SpecializationSummary = new SpecializationSummary 
              { 
               Name = s.Specialization.Name 
              } 
             }), 
        SubSpecializationSummaries = (
            from ssp in s.StudentSubSpecializations 
            select new StudentSubSpecializationSummary 
             { 
              StudentSubSpecializationID = ssp.StudentSubSpecializationID, 
              SubSpecializationSummary = new SubSpecializationSummary 
              { 
               Name = s.SubSpecialization.Name 
              } 
             }) 
}; 

我的投影語句出現,使實體框架生成的SQL語句UNION語句,下面是一個片段只(代碼改爲隱藏自有房產的物業 - 可能有錯別字):

{SELECT 
[UnionAll1].[StudentID] AS [C1], 
[UnionAll1].[StudentID1] AS [C2], 
[UnionAll1].[Title] AS [C3], 
[UnionAll1].[FullName] AS [C4], 
[UnionAll1].[Qualifications] AS [C5], 
[UnionAll1].[Gender] AS [C6], 
[UnionAll1].[C1] AS [C9], 
[UnionAll1].[StudentSpecializationID] AS [C10], 
[UnionAll1].[StudentSpecializationID1] AS [C11], 
[UnionAll1].[StudentSpecializationID2] AS [C12], 
[UnionAll1].[Name] AS [C13], 
[UnionAll1].[C2] AS [C14], 
[UnionAll1].[C3] AS [C15], 
[UnionAll1].[C4] AS [C16], 
[UnionAll1].[C5] AS [C17] 
FROM (SELECT 
    CASE WHEN ([Join1].[StudentSpecializationID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1], 
    [Extent1].[StudentID] AS [StudentID], 
    [Extent1].[StudentID] AS [StudentID1], 
    [Extent1].[Title] AS [Title], 
    [Extent1].[FullName] AS [FullName], 
    [Extent1].[Qualifications] AS [Qualifications], 
    [Extent1].[Gender] AS [Gender], 
    [Join1].[StudentSpecializationID] AS [StudentSpecializationID], 
    [Join1].[StudentSpecializationID] AS [StudentSpecializationID1], 
    [Join1].[StudentSpecializationID] AS [StudentSpecializationID2], 
    [Join1].[Name] AS [Name], 
    CAST(NULL AS int) AS [C2], 
    CAST(NULL AS int) AS [C3], 
    CAST(NULL AS int) AS [C4], 
    CAST(NULL AS varchar(1)) AS [C5] 
    FROM [dbo].[Student] AS [Extent1] 
    LEFT OUTER JOIN (SELECT [Extent2].[StudentSpecializationID] AS [StudentSpecializationID], [Extent2].[StudentID] AS [StudentID], [Extent3].[Name] AS [Name] 
     FROM [dbo].[StudentSpecialization] AS [Extent2] 
     INNER JOIN [dbo].[Specialization] AS [Extent3] ON [Extent2].[SpecializationID] = [Extent3].[SpecializationID]) AS [Join1] ON [Extent1].[StudentID] = [Join1].[StudentID] 
UNION ALL 
    SELECT 
    2 AS [C1], 
    [Extent4].[StudentID] AS [StudentID], 
    [Extent4].[StudentID] AS [StudentID1], 
    [Extent4].[Title] AS [Title], 
    [Extent4].[FullName] AS [FullName], 
    [Extent4].[Qualifications] AS [Qualifications], 
    [Extent4].[Gender] AS [Gender], 
    CAST(NULL AS int) AS [C2], 
    CAST(NULL AS int) AS [C3], 
    CAST(NULL AS int) AS [C4], 
    CAST(NULL AS varchar(1)) AS [C5], 
    [Join3].[StudentSubSpecializationID] AS [StudentSubSpecializationID], 
    [Join3].[StudentSubSpecializationID] AS [StudentSubSpecializationID1], 
    [Join3].[StudentSubSpecializationID] AS [StudentSubSpecializationID2], 
    [Join3].[Name] AS [Name] 
    FROM [dbo].[Student] AS [Extent4] 
    INNER JOIN (SELECT [Extent5].[StudentSubSpecializationID] AS [StudentSubSpecializationID], [Extent5].[StudentID] AS [StudentID], [Extent6].[Name] AS [Name] 
     FROM [dbo].[StudentSubSpecialization] AS [Extent5] 
     INNER JOIN [dbo].[SubSpecialization] AS [Extent6] ON [Extent5].[SubSpecializationID] = [Extent6].[SubSpecializationID]) AS [Join3] ON [Extent4].[StudentID] = [Join3].[StudentID]) AS [UnionAll1] 
ORDER BY [UnionAll1].[StudentID1] ASC, [UnionAll1].[C1] ASC} 

我不知道爲什麼這裏正在使用的聯合。也許我使用投影很差。雖然我注意到當您的L2E語句中包含兩個或更多預測時,UNIONS將顯示在SQL中。

我試過去除另一個方向的預測,但沒有成功嘗試使用連接,Froms ...似乎無法得到相關的子實體被返回。

由於性能方面的原因,我無法使用Include,因爲我使用了摘要對象。

我也在質疑我是否現在正確地做了這件事,即我是否正在返回嵌套相關(子)實體的正確方向?!?!也許我應該返回平坦的結果,例如學生,校園,專業化......將所有對象都放在同一層次上,即刪除層次結構。

問題

如果我建這與T-SQL,我將使用內部&左外連接返回相關的子嵌套實體,也篩選學生。這是我試圖用Linq實體實現的。我怎樣才能做到這一點?例如。與連接,投影或其他...(沒有UNIONs和Cast(NULL)s ...

欣賞任何幫助,即使它只是指向正確的方向,因爲我真的被困在這裏。謝謝。

回答

0

查詢執行得不好嗎?如果沒有,不要擔心生成的SQL。事實上,使用union all可能是實現這一目標的最佳方式。使用多個連接創建一個非常複雜的查詢可能會比多個簡單查詢結合在一起的速度要慢union all

+0

對於少量記錄,查詢運行不佳,但我需要執行SQL分析來確定。但好的一點是,所有人對多個聯盟都沒有想到這一點。將在此讀取確認。謝謝,這有助於。 – 2014-10-20 02:05:48

相關問題