2012-11-28 45 views
1

我想知道爲什麼INNER JOINs生成而不是左,以及爲什麼整個視圖在連接之前選擇,而不是隻添加左連接視圖。Linq實體查詢添加內部連接,而不是左連接

我想發佈一張信息表,分佈在幾個表。基本上我想根據日期進行搜索,並返回本月昨天,本月發生的所有事件的信息 - 無論用戶選擇什麼。查詢很長。我將DefaultIfEmpty添加到除了主表之外的所有表中,以試圖獲得LEFT JOIN,但它只是一團糟。

using (TransitEntities t = new TransitEntities()) 
    { 
    var charters = from c in t.tblCharters 
join v in t.tblChartVehicles.DefaultIfEmpty() 
on c.Veh 
equals v.ChartVehID 
join n in t.tblNACharters.DefaultIfEmpty() 
on c.Dpt.Substring(c.Dpt.Length - 1) 
equals SqlFunctions.StringConvert((double)n.NAID) 
join r in t.tblChartReqs.DefaultIfEmpty() 
on c.ChartReqID 
equals r.ChartReqID 
join f in t.tblCharterCustomers.DefaultIfEmpty() 
on c.Dpt 
equals (f.DptID == "NONAFF" ? SqlFunctions.StringConvert((double)f.CustID) : f.DptID) 
join d in t.tblChartReqDocs.DefaultIfEmpty() 
on c.Attach 
equals SqlFunctions.StringConvert((double)d.DocID) 
join s in t.tblChartSupAttaches.DefaultIfEmpty() 
on c.SupAttach 
equals SqlFunctions.StringConvert((double)s.DocID) 
join p in (from e in t.v_EmpData select new {e.UIN, e.First, e.Last}).DefaultIfEmpty() 
on c.TakenUIN 
equals p.UIN 
where c.BeginTime > EntityFunctions.AddYears(DateTime.Now,-1) 
select new 
{ 
    ChartID = c.ChartID, 
    Status = c.Status, 
    ... 
    Website = r.Website, 
}; 
//select today's events 
gvCharters.DataSource = charters.Where(row => (row.BeginTime.Value >= midnight && row.BeginTime.Value < midnight1)); 

這將導致非常令人費解的SQL:

SELECT 
    [Extent1].[ChartID] AS [ChartID], 
    [Extent1].[Status] AS [Status], 
    ... 
    [Join5].[Website] AS [Website], 

    FROM  [dbo].[tblCharters] AS [Extent1] 
    INNER JOIN (SELECT [Extent2].[ChartVehID] AS [ChartVehID], [Extent2].[Descr] AS [Descr] 
     FROM (SELECT 1 AS X) AS [SingleRowTable1] 
     LEFT OUTER JOIN [dbo].[tblChartVehicles] AS [Extent2] ON 1 = 1) AS [Join1] ON ([Extent1].[Veh] = [Join1].[ChartVehID]) OR (([Extent1].[Veh] IS NULL) AND ([Join1].[ChartVehID] IS NULL)) 
    INNER JOIN (SELECT [Extent3].[NAID] AS [NAID], [Extent3].[Descr] AS [Descr] 
     FROM (SELECT 1 AS X) AS [SingleRowTable2] 
     LEFT OUTER JOIN [dbo].[tblNACharter] AS [Extent3] ON 1 = 1) AS [Join3] ON ((SUBSTRING([Extent1].[Dpt], ((LEN([Extent1].[Dpt])) - 1) + 1, (LEN([Extent1].[Dpt])) - ((LEN([Extent1].[Dpt])) - 1))) = (STR(CAST([Join3].[NAID] AS float)))) OR ((SUBSTRING([Extent1].[Dpt], ((LEN([Extent1].[Dpt])) - 1) + 1, (LEN([Extent1].[Dpt])) - ((LEN([Extent1].[Dpt])) - 1)) IS NULL) AND (STR(CAST([Join3].[NAID] AS float)) IS NULL)) 
    INNER JOIN (SELECT [Extent4].[ChartReqID] AS [ChartReqID], [Extent4].[Event] AS [Event], [Extent4].[ContactName] AS [ContactName], [Extent4].[ContactPhone] AS [ContactPhone], [Extent4].[Website] AS [Website] 
     FROM (SELECT 1 AS X) AS [SingleRowTable3] 
     LEFT OUTER JOIN [dbo].[tblChartReq] AS [Extent4] ON 1 = 1) AS [Join5] ON ([Extent1].[ChartReqID] = [Join5].[ChartReqID]) OR (([Extent1].[ChartReqID] IS NULL) AND ([Join5].[ChartReqID] IS NULL)) 
    INNER JOIN (SELECT [Extent5].[CustID] AS [CustID], [Extent5].[Dpt] AS [Dpt], [Extent5].[DptID] AS [DptID] 
     FROM (SELECT 1 AS X) AS [SingleRowTable4] 
     LEFT OUTER JOIN [dbo].[tblCharterCustomers] AS [Extent5] ON 1 = 1) AS [Join7] ON ([Extent1].[Dpt] = (CASE WHEN (N'NONAFF' = [Join7].[DptID]) THEN STR(CAST([Join7].[CustID] AS float)) ELSE [Join7].[DptID] END)) OR (([Extent1].[Dpt] IS NULL) AND (CASE WHEN (N'NONAFF' = [Join7].[DptID]) THEN STR(CAST([Join7].[CustID] AS float)) ELSE [Join7].[DptID] END IS NULL)) 
    INNER JOIN (SELECT [Extent6].[DocID] AS [DocID], [Extent6].[FileName] AS [FileName] 
     FROM (SELECT 1 AS X) AS [SingleRowTable5] 
     LEFT OUTER JOIN [dbo].[tblChartReqDocs] AS [Extent6] ON 1 = 1) AS [Join9] ON ([Extent1].[Attach] = (STR(CAST([Join9].[DocID] AS float)))) OR (([Extent1].[Attach] IS NULL) AND (STR(CAST([Join9].[DocID] AS float)) IS NULL)) 
    INNER JOIN (SELECT [Extent7].[DocID] AS [DocID], [Extent7].[FileName] AS [FileName] 
     FROM (SELECT 1 AS X) AS [SingleRowTable6] 
     LEFT OUTER JOIN [dbo].[tblChartSupAttach] AS [Extent7] ON 1 = 1) AS [Join11] ON ([Extent1].[SupAttach] = (STR(CAST([Join11].[DocID] AS float)))) OR (([Extent1].[SupAttach] IS NULL) AND (STR(CAST([Join11].[DocID] AS float)) IS NULL)) 
    INNER JOIN (SELECT [Extent8].[First] AS [First], [Extent8].[Last] AS [Last], [Extent8].[UIN] AS [UIN] 
     FROM (SELECT 1 AS X) AS [SingleRowTable7] 
     LEFT OUTER JOIN (SELECT 
      [v_EmpData].[First] AS [First], 
      [v_EmpData].[Last] AS [Last], 
      [v_EmpData].[Legal] AS [Legal], 
      [v_EmpData].[Name] AS [Name], 
      [v_EmpData].[Email] AS [Email], 
      [v_EmpData].[UIN] AS [UIN], 
      [v_EmpData].[UserNM] AS [UserNM], 
      [v_EmpData].[Worker] AS [Worker], 
      [v_EmpData].[SUPERVISORNUM] AS [SUPERVISORNUM], 
      [v_EmpData].[Supervisor] AS [Supervisor], 
      [v_EmpData].[EmpArea] AS [EmpArea], 
      [v_EmpData].[Title] AS [Title], 
      [v_EmpData].[FullName] AS [FullName], 
      [v_EmpData].[HireDate] AS [HireDate], 
      [v_EmpData].[WORKERTYPENM] AS [WORKERTYPENM], 
      [v_EmpData].[Birth] AS [Birth], 
      [v_EmpData].[HOMESTREET] AS [HOMESTREET], 
      [v_EmpData].[HOMECITY] AS [HOMECITY], 
      [v_EmpData].[HOMEZIP] AS [HOMEZIP], 
      [v_EmpData].[HOMESTATE] AS [HOMESTATE], 
      [v_EmpData].[PicID] AS [PicID], 
      [v_EmpData].[WorkPhone] AS [WorkPhone], 
      [v_EmpData].[HomePhone] AS [HomePhone], 
      [v_EmpData].[WorkCellPhone] AS [WorkCellPhone] 
     FROM [dbo].[v_EmpData] AS [v_EmpData]) AS [Extent8] ON 1 = 1) AS [Join13] ON ([Extent1].[TakenUIN] = [Join13].[UIN]) OR (([Extent1].[TakenUIN] IS NULL) AND ([Join13].[UIN] IS NULL)) 
WHERE ([Extent1].[BeginTime] > (DATEADD (year, -1, SysDateTime()))) 
    AND ('C' <> [Extent1].[Status]) 
    AND ([Extent1].[BeginTime] >= '11/28/2012 12:00:00 AM') 
    AND ([Extent1].[BeginTime] < '11/29/2012 12:00:00 AM') 

這是我原來的SQL查詢看起來像什麼,我希望它會更接近:

SELECT 
    ChartID, 
    c.Status, 
    ... 
    r.Website As Website, 

FROM tblChartersNew c 
    LEFT JOIN (SELECT [Dpt],[DptID] FROM [DRVRDiscipline].[dbo].[tblCharterCustomers] Where Valid=1 and DptID <> 'NONAFF' UNION SELECT Dpt, CONVERT(nvarchar,CustID) AS DptID FROM [DRVRDiscipline].[dbo].[tblCharterCustomers] Where Valid=1 and DptID = 'NONAFF') f 
    ON RTRIM(c.Dpt) = f.DptID LEFT JOIN [tskronos].WfcSuite.dbo.VP_ALLPERSONV42 p ON p.PersonNUM = c.TakenUIN 
    LEFT JOIN tblChartVehicles v ON v.ChartVehID = c.Veh 
    LEFT JOIN tblNACharter n ON CAST(n.NAID AS varchar) = RIGHT(c.Dpt, LEN(c.Dpt)-1) 
    LEFT JOIN tblChartReq r 
    ON r.ChartReqID = c.ChartReqID 
WHERE CONVERT(datetime,CONVERT(char(10),c.BeginTime,101)) = (SELECT TOP 1 CONVERT(datetime,CONVERT(char(10),BeginTime,101)) from tblChartersNew WHERE CONVERT(datetime,CONVERT(char(10),BeginTime,101)) >= CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) ORDER BY BeginTime) 
    AND NOT c.ChartReqID IS NULL 
ORDER BY BeginTime, ISNULL(f.Dpt,c.Dpt) 

我也在視圖中添加一個Select New以避免在我只需要三個時選擇所有的列,但它似乎沒有什麼區別。不添加LEFT JOIN v_EmpData,而是添加LEFT OUTER JOIN,然後選擇視圖中的所有列。它似乎忽略了Select New。

我真的很想過渡到使用Linq的實體爲我的大部分查詢,因爲intellisense使得它更容易確保它是正確的,並有查詢的變化,而不必爲每個單獨的功能,但也許我需要堅持使用普通的舊SQL。我知道這足以讓一團糟。有什麼建議麼?

回答

0

適用於您需要的複雜查詢。

我會建議看看FunctionImport。

MSDN Function Import

這將節省您創建一個LINQ的頭痛,這將是1:1到你的預期生成的SQL。

+0

經過許多令人沮喪的日子,我注意到我沒有用過。 –

+0

經過許多令人沮喪的日子,我注意到我沒有用過。由此產生的SQL仍然是垃圾,所以我可能不會使用它,但它的工作原理。我仍然不明白爲什麼它只是將左連接添加到內連接而不是直接左連接,但我認爲這對linq來說太複雜了。 從C在t.tblCharters 在t.tblChartVehicles 上c.Veh加入v 等於v.ChartVehID到list1from V1在list1.DefaultIfEmpty() ... 選擇新{ 輛= v1.Descr, ...} –