2012-12-28 19 views
1

我有一個查詢:Linq To SQL。如何防止使用應用運營商

var contactInfos = from person in persons 

        join tempDesiredCar in desiredCars on person.contact_id equals tempDesiredCar.groupEntity_id 
            into tempDesiredCars 
        from desiredCar in tempDesiredCars.DefaultIfEmpty() 
        select new {name = person.name, car = desiredCar.name}; 

此代碼轉換爲SQL:

SELECT [t1].[name], [t19].[name] AS [car] 
FROM [dbo].[Person] AS [t1] 
CROSS APPLY ((
     SELECT NULL AS [EMPTY] 
     ) AS [t6] 
    OUTER APPLY (
     SELECT [t18].[name] 
     FROM (
      SELECT [t17].[contact_id], [t17].[name] 
      FROM (
       SELECT [t7].[contact_id], [t11].[name] 
       FROM [dbo].[DesiredCar] AS [t7] 
       INNER JOIN (
        SELECT MAX([t9].[value]) AS [value] 
        FROM (
         SELECT [t8].[id] AS [value], [t8].[contact_id] 
         FROM [dbo].[DesiredCar] AS [t8] 
         ) AS [t9] 
        GROUP BY [t9].[contact_id] 
        ) AS [t10] ON ([t7].[id]) = [t10].[value] 
       LEFT OUTER JOIN [dbo].[FamilyModel] AS [t11] ON [t11].[id] = [t7].[model] 
       WHERE [t7].[model] IS NOT NULL 
       UNION 
       SELECT [t12].[contact_id], [t16].[name] 
       FROM [dbo].[DesiredCar] AS [t12] 
       INNER JOIN (
        SELECT MAX([t14].[value]) AS [value] 
        FROM (
         SELECT [t13].[id] AS [value], [t13].[contact_id] 
         FROM [dbo].[DesiredCar] AS [t13] 
         ) AS [t14] 
        GROUP BY [t14].[contact_id] 
        ) AS [t15] ON ([t12].[id]) = [t15].[value] 
       LEFT OUTER JOIN [dbo].[CarBrand] AS [t16] ON [t16].[id] = [t12].[carBrand_id] 
       WHERE [t12].[carBrand_id] IS NOT NULL 
       ) AS [t17] 
      ) AS [t18] 
     where [t1].[contact_id] = [t18].[contact_id] 
     ) AS [t19]) 

該代碼用途應用。如果替換通過左連接應用代碼運行更快在幾次。 如何強制Linq使用左連接生成代碼?

+1

LINQ to SQL不是編寫SQL的「更好」方式,也不是它取代SQL。手動編寫這樣一個簡單的語句更容易,更快,並讓L2S從結果中創建新對象 –

+1

此解決方案使自動重構不可用。 – Coder

+1

請向我們展示完整的LINQ查詢... – usr

回答

1

我發現LINQ使用apply運算符的原因。操作數正在檢查,該連接中的外鍵是否存在依賴關係,或者沒有。如果它只是一個表 - linq使用「左連接」。如果子查詢包含Group By,Order By with「equals」中使用的列,則LINQ使用「外部應用」。 在LINQ JOIN中使用簡單的子查詢。

+1

我一直在閱讀你的答案10分鐘,我仍然不明白。我不明白你的句子,我不明白你的意思是「簡單的子查詢」。我試圖避免一個「APPLY」操作員,由於不同的原因。 – migle

0

我無法找到a)加入並應用產生不同計劃的原因b)LINQ完全使用應用程序。這是一個奇怪的例子。

我試圖想出解決方法,希望他們的工作:

//project only the needed columns 
var contactInfos = from person in persons 
        join tempDesiredCar in 
         desiredCars.Select(x => new { x.groupEntity_id, x.name }) 
         on person.contact_id equals tempDesiredCar.groupEntity_id 
         into tempDesiredCars 
        from desiredCar in tempDesiredCars.DefaultIfEmpty() 
        select new { name = person.name, car = desiredCar.name }; 

//change join to from 
var contactInfos = from person in persons 
        from desiredCar in 
         desiredCars.Select(x => new { x.groupEntity_id, x.name }) 
            .Where(x => person.contact_id = x.groupEntity_id) 
            .DefaultIfEmpty() 
        select new { name = person.name, car = desiredCar.name }; 

這些都只是推測性的重寫。我希望他們巧合運作......我知道這不是解決問題的好方法,但在這種奇怪的情況下,這是我能提供的最好的方式。

+0

第二個LINQ表達式中,LINQ沒有完全翻譯成SQL。 – Coder

0

我檢查了查詢計劃。

應用計劃使用嵌套循環將表連接在一起。對於Person表中的每條記錄,它讀取DesiredCars表中的每條記錄。你是否真的需要在數據庫中找到每個人需要的汽車?如果不是,請考慮先過濾一下Person表。

連接計劃使用Hashmatching將表連接在一起。它只讀取一次表格,生成一張表格的地圖,並在第二張表格上使用該地圖。優化者指出了一些索引建議。這些建議可能有助於兩個計劃。

 <MissingIndexes> 
      <MissingIndexGroup Impact="12.6549"> 
      <MissingIndex Database="[AudiCRM]" Schema="[dbo]" Table="[DesiredCar]"> 
       <ColumnGroup Usage="INEQUALITY"> 
       <Column Name="[carBrand_id]" ColumnId="13" /> 
       </ColumnGroup> 
       <ColumnGroup Usage="INCLUDE"> 
       <Column Name="[id]" ColumnId="1" /> 
       <Column Name="[contact_id]" ColumnId="2" /> 
       </ColumnGroup> 
      </MissingIndex> 
      </MissingIndexGroup> 
      <MissingIndexGroup Impact="12.6549"> 
      <MissingIndex Database="[AudiCRM]" Schema="[dbo]" Table="[DesiredCar]"> 
       <ColumnGroup Usage="INEQUALITY"> 
       <Column Name="[model]" ColumnId="3" /> 
       </ColumnGroup> 
       <ColumnGroup Usage="INCLUDE"> 
       <Column Name="[id]" ColumnId="1" /> 
       <Column Name="[contact_id]" ColumnId="2" /> 
       </ColumnGroup> 
      </MissingIndex> 
      </MissingIndexGroup> 
     </MissingIndexes>