我有3张桌子:
现在,如何从Delivery
表中获取一个集合,该集合将从仅执行一个lambda查询的其他表中获取DriverNames
?
需要考虑的事项:
当DriverType
为Internal
时,它应该从DriverNames
表格中获取InternalDriver
当DriverType
为External
时,它应该从DriverNames
表格中获取ExternalDriver
答案 0 :(得分:2)
您可以单独加入两种类型的驱动程序,然后在可接受的情况下连接结果:
var deliveries = new Delivery[] { };
var internalDrivers = new Driver[] { /*...*/ };
var externalDrivers = new Driver[] { /*...*/ };
var deliveryModels = deliveries.Where(dl => dl.DriverType == "Internal")
.Join(internalDrivers, delivery => delivery.DriverId, driver => driver.Id,
(dl, dr) => new DeliveryModel {DeliveryId = dl.Id, DriverName = dr.DriverName})
.Concat(deliveries.Where(dl => dl.DriverType == "External")
.Join(externalDrivers, delivery => delivery.DriverId, driver => driver.Id,
(dl, dr) => new DeliveryModel {DeliveryId = dl.Id, DriverName = dr.DriverName}));
//....
public class DeliveryModel
{
public int DeliveryId { get; set; }
public string DriverName { get; set; }
}
或者,为避免连接,您可以使用GroupJoin
两次使用DriverId和DriverType的组合键来连接内部和外部驱动程序,并查看匹配的内容:
var deliveryModels = deliveries.GroupJoin(internalDrivers,
delivery => (delivery.DriverType, delivery.DriverId), driver => ("Internal", driver.Id),
(dl, dr) => (dl, dr))
.GroupJoin(externalDrivers,
internalDriversJoin => (internalDriversJoin.dl.DriverType, internalDriversJoin.dl.DriverId),
extDr => ("External", extDr.Id),
(internalJoinResult, dr) => new DeliveryModel
{
DeliveryId = internalJoinResult.dl.Id,
DriverName = (internalJoinResult.dr.FirstOrDefault() ?? dr?.FirstOrDefault())?.DriverName
});
我不知道在第二个查询中会生成哪个SQL(我希望有两个LEFT JOIN,但不确定)以及性能如何:它可能比第一个查询更好,或者可能更糟糕 - 在大数据场景中使用之前测试一下......
如果对于LINQ to对象,我会使用第一个查询 - 它肯定更简单,并且应该更快,因为在内存中创建的对象更少。
答案 1 :(得分:0)
我认为你可以这样做:
var d = from del in db.deliveries
join intdrv in db.internalDrivers on new { t = del.DriverType, i = del.DriverId }
equals new { t = "Internal", i = intdrv.DriverId } into tdi
from di in tdi.DefaultIfEmpty()
join extdrv in db.externalDrivers on new { t = del.DriverType, i = del.DriverId }
equals new { t = "External", i = extdrv.DriverId } into tde
from de in tde.DefaultIfEmpty()
where (di ?? de) != null
select new
{
DeliveryId = del.Id,
DriverName = (di ?? de).DriverName
};
基本上它会执行两个左连接,每个表一个,然后使用空合并运算符来选择第一个非空结果。在哪里确保找到其中一个。
答案 2 :(得分:-1)
我没考试。但你可以尝试我的解决方案。希望能帮忙,我的朋友:
var data = from u in Delivery
select new
{
Id = u.Id,
DriverName = u.DriverType == "Internal" ? u.InternalDriver.DriverName : u.ExternalDriver.DriverName;
}