2013-12-19 112 views
0

我有這樣的架構(我做了簡化它,這樣我可以很容易地張貼在這裏)難度SQL查詢轉換爲LINQ到實體查詢

diagram

這個sql查詢,變量/進入點會是in (1,2,3)

SELECT c1.ChildId1 
     , c1.Info1 
     , m1.Info 
     , l1.Description1 
     , l2.Description2 
     , l2.Description3 

from dbo.ChildTable1 c1 

     inner join dbo.MasterTable m1 
      on m1.MasterId = c1.MasterId 

     inner join dbo.LookupTable1 l1 
      on c1.LookupId1 = l1.LookupId1    

     inner join dbo.ChildTable2 c2    
      on m1.MasterId = c2.MasterId 

     inner join dbo.LookupTable2 l2 
      on c2.LookupId2 = l2.LookupId2 

where c1.ChildId1 in (select max(c.ChildId1) 
         from dbo.ChildTable1 c 
         where c.ExtraId in (1,2,3) 
         group by c.MasterId) 

       AND 

     c2.ChildId2 in (select max(c.ChildId2)        
         from dbo.ChildTable2 c 
         where c.MasterId = m1.MasterId 
         group by c.MasterId) 

我設法寫這個LINQ到實體查詢,它返回相同的結果,到目前爲止

var value = (new int?[] { 1, 2, 3 }); 

var query = (from c1 in db.ChildTable1 
       where db.ChildTable1.Where(x => value.Contains(x.ExtraId)).GroupBy(x => x.MasterId).Select(x => x.Max(y => y.ChildId1)).Contains(c1.ChildId1) 
       select new 
       { 
        c1.ChildId1, 
        c1.Info1, 
        c1.MasterTable.Info, 
        c1.LookupTable1.Description1, 
        db.LookupTable2.Where(x => x.LookupId2 == c1.MasterTable.ChildTable2.OrderByDescending(y=>y.ChildId2).FirstOrDefault().LookupId2).FirstOrDefault().Description2, 
        db.LookupTable2.Where(x => x.LookupId2 == c1.MasterTable.ChildTable2.OrderByDescending(y=>y.ChildId2).FirstOrDefault().LookupId2).FirstOrDefault().Description3 
       }).ToList(); 

,並生成該SQL查詢

SELECT 
[Filter3].[ChildId1] AS [ChildId1], 
[Filter3].[Info1] AS [Info1], 
[Filter3].[Info] AS [Info], 
[Filter3].[Description1] AS [Description1], 
[Limit2].[Description2] AS [Description2], 
[Limit4].[Description3] AS [Description3] 
FROM (SELECT [Extent1].[ChildId1] AS [ChildId1], [Extent1].[MasterId] AS [MasterId1], [Extent1].[Info1] AS [Info1], [Extent2].[Info] AS [Info], [Extent3].[Description1] AS [Description1] 
    FROM [dbo].[ChildTable1] AS [Extent1] 
    INNER JOIN [dbo].[MasterTable] AS [Extent2] ON [Extent1].[MasterId] = [Extent2].[MasterId] 
    INNER JOIN [dbo].[LookupTable1] AS [Extent3] ON [Extent1].[LookupId1] = [Extent3].[LookupId1] 
    WHERE EXISTS (SELECT 
     1 AS [C1] 
     FROM (SELECT 
      [Extent4].[MasterId] AS [K1], 
      MAX([Extent4].[ChildId1]) AS [A1] 
      FROM [dbo].[ChildTable1] AS [Extent4] 
      WHERE [Extent4].[ExtraId] IN (1, 2, 3) 
      GROUP BY [Extent4].[MasterId] 
     ) AS [GroupBy1] 
     WHERE [GroupBy1].[A1] = [Extent1].[ChildId1] 
    )) AS [Filter3] 
OUTER APPLY (SELECT TOP (1) 
    [Extent5].[Description2] AS [Description2] 
    FROM [dbo].[LookupTable2] AS [Extent5] 
    INNER JOIN (SELECT TOP (1) [Project2].[LookupId2] AS [LookupId2] 
     FROM (SELECT 
      [Extent6].[ChildId2] AS [ChildId2], 
      [Extent6].[LookupId2] AS [LookupId2] 
      FROM [dbo].[ChildTable2] AS [Extent6] 
      WHERE [Filter3].[MasterId1] = [Extent6].[MasterId] 
     ) AS [Project2] 
     ORDER BY [Project2].[ChildId2] DESC) AS [Limit1] ON [Extent5].[LookupId2] = [Limit1].[LookupId2]) AS [Limit2] 
OUTER APPLY (SELECT TOP (1) 
    [Extent7].[Description3] AS [Description3] 
    FROM [dbo].[LookupTable2] AS [Extent7] 
    INNER JOIN (SELECT TOP (1) [Project4].[LookupId2] AS [LookupId2] 
     FROM (SELECT 
      [Extent8].[ChildId2] AS [ChildId2], 
      [Extent8].[LookupId2] AS [LookupId2] 
      FROM [dbo].[ChildTable2] AS [Extent8] 
      WHERE [Filter3].[MasterId1] = [Extent8].[MasterId] 
     ) AS [Project4] 
     ORDER BY [Project4].[ChildId2] DESC) AS [Limit3] ON [Extent7].[LookupId2] = [Limit3].[LookupId2]) AS [Limit4] 

我的問題很簡單,我怎麼能優化這個LINQ查詢?

+0

我想知道它是否會更好,繼續只使用LINQ表達式你在'c1'上的'where'而不是'db.ChildTable1.Where(.....)'。我不知道,但我會認爲這會觸發標準LINQ表達式創建的循環內的另一個循環,因爲您已經可以在其中進行分組了。 – TyCobb

+0

如何將SQL查詢定義爲服務器上的視圖,然後針對它執行簡單的LINQ選擇。在數據庫服務器上保留查詢的複雜性。 – swandog

+0

@swandog,我可以這樣做,我只需要用我的1,2,3值傳入一個varchar(max),並使用表函數將它解析到我的IN子句的表中。但如果我可以,我想避免這樣做 – Fredou

回答

0

我想我找到了如何

var query = (from c1 in db.ChildTable1 
      join c2 in db.ChildTable2 on c1.MasterId equals c2.MasterId 
      let t1 = db.ChildTable1.Where(x => x.MasterId == c2.MasterId).GroupBy(x => x.MasterId).Select(x => x.Max(y => y.ChildId1)) 
      let t2 = db.ChildTable2.Where(x => x.MasterId == c2.MasterId).GroupBy(x => x.MasterId).Select(x => x.Max(y => y.ChildId2)) 
      where value.Contains(c1.ExtraId) && t1.Contains(c1.ChildId1) && t2.Contains(c2.ChildId2) 

      select new 
      { 
       c1.ChildId1, 
       c1.MasterTable.Info, 
       c1.Info1, 
       c2.Info2, 
       c1.LookupTable1.Description1, 
       c2.LookupTable2.Description2, 
       c2.LookupTable2.Description3 
      }).ToList(); 

這確實(非常類似於原來的SQL查詢)

SELECT 
[Extent1].[ChildId1] AS [ChildId1], 
[Extent3].[Info] AS [Info], 
[Extent1].[Info1] AS [Info1], 
[Extent2].[Info2] AS [Info2], 
[Extent4].[Description1] AS [Description1], 
[Extent5].[Description2] AS [Description2], 
[Extent5].[Description3] AS [Description3] 
FROM  [dbo].[ChildTable1] AS [Extent1] 
INNER JOIN [dbo].[ChildTable2] AS [Extent2] ON [Extent1].[MasterId] = [Extent2].[MasterId] 
INNER JOIN [dbo].[MasterTable] AS [Extent3] ON [Extent1].[MasterId] = [Extent3].[MasterId] 
INNER JOIN [dbo].[LookupTable1] AS [Extent4] ON [Extent1].[LookupId1] = [Extent4].[LookupId1] 
INNER JOIN [dbo].[LookupTable2] AS [Extent5] ON [Extent2].[LookupId2] = [Extent5].[LookupId2] 
WHERE ([Extent1].[ExtraId] IN (1, 2, 3)) AND (EXISTS (SELECT 
    1 AS [C1] 
    FROM (SELECT 
     [Extent6].[MasterId] AS [K1], 
     MAX([Extent6].[ChildId1]) AS [A1] 
     FROM [dbo].[ChildTable1] AS [Extent6] 
     WHERE [Extent6].[MasterId] = [Extent2].[MasterId] 
     GROUP BY [Extent6].[MasterId] 
    ) AS [GroupBy1] 
    WHERE [GroupBy1].[A1] = [Extent1].[ChildId1] 
)) AND (EXISTS (SELECT 
    1 AS [C1] 
    FROM (SELECT 
     [Extent7].[MasterId] AS [K1], 
     MAX([Extent7].[ChildId2]) AS [A1] 
     FROM [dbo].[ChildTable2] AS [Extent7] 
     WHERE [Extent7].[MasterId] = [Extent2].[MasterId] 
     GROUP BY [Extent7].[MasterId] 
    ) AS [GroupBy2] 
    WHERE [GroupBy2].[A1] = [Extent2].[ChildId2] 
))