2012-11-28 42 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, ...} –