繁体   English   中英

如何在不使用查询语法的情况下在Entity Framework中执行左外连接?

[英]How to do a left outer join in Entity Framework without using the query syntax?

我正在尝试使用linq的查询语法将此查询转换为基于方法的语法。

这是查询:

  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查询(当然,关于如何在程序中使用数据,它具有不同的含义):

{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}

您的答案将会非常有用,非常感谢!

通常,您可以通过访问查询的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 })
);
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>();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM