如何在实体框架中执行左外连接而不使用查询语法
本文关键字:连接 语法 查询 实体 框架 执行 | 更新日期: 2023-09-27 18:02:24
我正在尝试使用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>();