Linq to entities查询添加内连接而不是左连接

时间:2012-11-28 16:47:11

标签: view linq-to-entities left-join inner-join

我想知道为什么生成INNER JOIN而不是LEFT以及为什么在连接之前选择整个视图而不是仅添加LEFT JOIN视图。

我正在尝试发布一张分散在几张桌子上的信息表。基本上我想按日期搜索并返回今天,昨天,本月发生的事件的所有信息 - 无论用户选择什么。查询很长。我将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 to Entities来处理我的大多数查询,因为intellisense让它更容易确保它是正确的,并且有各种各样的查询,而不必为每个查询提供单独的函数,但也许我需要坚持使用普通的旧SQL。我知道这足以造成一团糟。有什么建议吗?

1 个答案:

答案 0 :(得分:0)

对于您需要的复杂查询。

我建议查看FunctionImport。

MSDN Function Import

这样可以省去创建LINQ的麻烦,LINQ与预期生成的SQL的比例为1:1。