2016-08-14 30 views
5

我試圖將這個查詢使用linq的查詢語法轉換爲基於方法的語法。如何在不使用查詢語法的情況下在Entity Framework中執行左外連接?

這裏的查詢:

var products = from p in context.Products 
       join t in context.TopSellings 
       on p.Id equals t.Id into g 
       from tps in g.DefaultIfEmpty() 
       orderby tps.Rating descending 
       select new 
       { 
        Name = p.Name, 
        Rating = tps.Rating == null ? 0 : tps.Rating 
       }; 

上面的查詢生成這個SQL查詢:

{SELECT 
    [Project1].[Id] AS [Id], 
    [Project1].[Name] AS [Name], 
    [Project1].[C1] AS [C1] 
    FROM (SELECT 
     [Extent1].[Id] AS [Id], 
     [Extent1].[Name] AS [Name], 
     CASE WHEN ([Extent2].[Rating] IS NULL) THEN 0 ELSE [Extent2].[Rating] END AS [C1], 
     [Extent2].[Rating] AS [Rating] 
     FROM [dbo].[Products] AS [Extent1] 
     LEFT OUTER JOIN [dbo].[TopSellings] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Id] 
    ) AS [Project1] 
    ORDER BY [Project1].[Rating] DESC} 

到目前爲止,我已經試過是這樣的:

var products = context.Products 
    .Join(inner: context.TopSellings.DefaultIfEmpty(), 
      outerKeySelector: c => c.Id, innerKeySelector: y => y.Id, 
      resultSelector: (j, k) => new { Name = j.Name, Rating = k.Rating == null ? 0 : k.Rating }) 
    .OrderByDescending(p => p.Rating); 

和這個產生了一個不同的sql查詢(關於數據是如何的,這當然有不同的含義) ng在程序中使用):

{SELECT 
    [Project1].[Id] AS [Id], 
    [Project1].[Name] AS [Name], 
    [Project1].[C1] AS [C1] 
    FROM (SELECT 
     [Extent1].[Id] AS [Id], 
     [Extent1].[Name] AS [Name], 
     CASE WHEN ([Join1].[Rating] IS NULL) THEN 0 ELSE [Join1].[Rating] END AS [C1] 
     FROM [dbo].[Products] AS [Extent1] 
     INNER JOIN (SELECT [Extent2].[Id] AS [Id], [Extent2].[Rating] AS [Rating] 
      FROM (SELECT 1 AS X) AS [SingleRowTable1] 
      LEFT OUTER JOIN [dbo].[TopSellings] AS [Extent2] ON 1 = 1) AS [Join1] ON [Extent1].[Id] = [Join1].[Id] 
    ) AS [Project1] 
    ORDER BY [Project1].[C1] DESC} 

你的答案會很有幫助,非常感謝!

+0

這種轉換是沒有意義的我,但無論如何,等效方法的語法會用'GroupJoin'其次是'SelectMany',希望你能自己從那裏做。 –

+0

請參閱msdn:https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – jdweng

+0

@IvanStoev純粹是爲了學習的目的。 –

回答

5

您通常可以通過訪問查詢的Expression屬性來從任何查詢表達式中獲得準確的表達式。然後分析這個表達並重現它。

var expr = products.Expression; 

另一方面,使用查詢語法的每個表達式都有一個直接轉換。與into連接的部分條款對應於GroupJoin(),而額外的from條款對應於SelectMany()。這將產生一個等效查詢:

var products = context.Products.GroupJoin(context.TopSellings, 
     p => p.Id, t => t.Id, (p, g) => new { p, g }) 
    .SelectMany(x => x.g.DefaultIfEmpty(), 
     (x, tps) => new { x.p, x.g, tps }) 
    .OrderByDescending(x => x.tps.Rating) 
    .Select(x => new { x.p.Name, Rating = x.tps.Rating == null ? 0 : x.tps.Rating }); 

但是你可以刪除一些冗餘切割變量不再使用,並採取了一些有用的運營商的優勢。請注意,它可能會影響生成的實際查詢,因此它不完全匹配,但它應該足夠接近。

var products = context.Products.GroupJoin(context.TopSellings, 
    p => p.Id, t => t.Id, 
    (p, g) => g.DefaultIfEmpty() 
     .OrderByDescending(tps => tps.Rating) 
     .Select(tps => new { p.Name, Rating = tps.Rating ?? 0 }) 
); 
+0

哇,就是這樣!感謝你,順便提一下,你提到的'表達'屬性,儘管它有點「神祕」的閱讀......如果你仔細分析它......這是有道理的!謝謝。 –

-2
using EF 

AAWSADBEntitiesContext = new AAWSA_DBEntitiesContext(); 
     // .Where(pp1 => ((zemechaObj.DriverId == pp1.DriverId) || (zemechaObj.DriverId == pp1.DriverId))) 
     var myresult =(from zemechaObj in AAWSADBEntitiesContext.WaterSupplyForwardedZemechResourses 
         where zemechaObj.CompanyId == companyId && zemechaObj.Status == WaterSupplyServiceRequest.Shared.ToString() 

         from driverObj in AAWSADBEntitiesContext.tbl_Driver 
           .Where(driver => ((zemechaObj.DriverId == driver.DriverId))) 
           .DefaultIfEmpty() 
          //fromBranch 
         from fromBranch in AAWSADBEntitiesContext.tbl_CompanyRegistrationInformation 
           .Where(fromB => ((zemechaObj.FromBranchId == fromB.CompanyId))) 

          //toBranch 
         from toBranch in AAWSADBEntitiesContext.tbl_CompanyRegistrationInformation 
           .Where(toB => ((zemechaObj.ToBranchId == toB.CompanyId))) 
           //vehicle 
          from vehicleObj in AAWSADBEntitiesContext.tbl_Vehicle 
           .Where(veh => ((zemechaObj.VehicleId == veh.VehicleId))) 
            .DefaultIfEmpty() 
           //assistant one 
         from DriverAssistantOneObj in AAWSADBEntitiesContext.tbl_DriverAssistant 
           .Where(driverAssistOne => ((zemechaObj.DriverAssitantFirstID == driverAssistOne.DriverAssistantId))) 
           .DefaultIfEmpty() 
          //assistant one 
         from DriverAssistantTwoObj in AAWSADBEntitiesContext.tbl_DriverAssistant 
           .Where(driverAssistTwo=> ((zemechaObj.DriverAssitantSecondID == driverAssistTwo.DriverAssistantId))) 
           .DefaultIfEmpty() 
          select new BranchResourceForZemechaEntities() 
          { 
           ForwaredResourseID = zemechaObj.ForwaredResourseID, 
           ServiceStartDate = zemechaObj.ServiceStartDate.ToString(), 
           ServiceEndDate = zemechaObj.ServiceEndDate.ToString(), 
           ForwaredDate = zemechaObj.ForwaredDate.ToString(), 
           Status = zemechaObj.Status, 
           Comment = zemechaObj.Comment, 
           //from Branch 
           FromBranchName = fromBranch.CompanyName, 
           //To Branch 
           ToBranchName = toBranch.CompanyName, 
           VehicleId = zemechaObj.VehicleId, 
           //Vehicle info 
           PlateNumber = vehicleObj.PlateNumber+" ", 
           DriverId = zemechaObj.DriverId, 
           //Driver Full Name 
           DriverFullName = driverObj.FirstName + " " + driverObj.MiddleName + " " + driverObj.LastName, 
           // Driver Assitant one Full Name 
           DriverAssitantFirstID = zemechaObj.DriverAssitantFirstID, 
           DriverAssistantOneFullName = DriverAssistantOneObj.FirstName + " " + DriverAssistantOneObj.MiddleName + " " + DriverAssistantOneObj.LastName, 
           // Driver Assitant Two Full Name 
           DriverAssitantSecondID = zemechaObj.DriverAssitantSecondID, 
           DriverAssistantTwoFullName = DriverAssistantTwoObj.FirstName + " " + DriverAssistantTwoObj.MiddleName + " " + DriverAssistantTwoObj.LastName, 

           CompanyId = zemechaObj.CompanyId, 
           FromBranchId = zemechaObj.FromBranchId, 
           ToBranchId = zemechaObj.ToBranchId, 
           BrLoggedUserId = zemechaObj.BrLoggedUserId.ToString() 

          }).ToList(); 
     return myresult.ToList<BranchResourceForZemechaEntities>(); 
+0

請不要只是轉儲一段代碼 - 而是解釋你的解決方案。 – Moritz

相關問題