2016-08-14 9 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); 

とこの1つは異なる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 ([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

うわー、それはまさにそれです!感謝の男、btw、あなたが言及したその '表現'のプロパティの良いヒントですが、それは読んでいくぶん "暗い"です...あなたがそれを慎重に分析すれば、それは理にかなっています!ありがとう。 –

-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

関連する問題