LINQ只保留了第一条记录的外部联接
我正在处理一个连接三个表的LINQ查询。对于LINQ只保留了第一条记录的外部联接,linq,Linq,我正在处理一个连接三个表的LINQ查询。对于订单和订单信息表,对于给定的订单id,我希望每个表中都有一条记录。但是,对于shipprate表,对于给定的订单id,可能有0条、1条或多条记录。对于这个表,我使用了一个左外连接。如果ShipRate表中存在0或1条记录,则下面显示的查询有效,但对于记录数大于1的情况,我只需要选择最近的ShipRate记录。我试图通过更换线路来实现这一点: 来自sr.DefaultIfEmpty()中的发货率 为此: 来自sr.OrderByDescending(r=
订单
和订单信息
表,对于给定的订单id
,我希望每个表中都有一条记录。但是,对于shipprate
表,对于给定的订单id
,可能有0条、1条或多条记录。对于这个表,我使用了一个左外连接。如果ShipRate
表中存在0或1条记录,则下面显示的查询有效,但对于记录数大于1的情况,我只需要选择最近的ShipRate
记录。我试图通过更换线路来实现这一点:
来自sr.DefaultIfEmpty()中的发货率
为此:
来自sr.OrderByDescending(r=>r.CreateDate)中的发货率。取(1)。DefaultIfEmpty()
但是查询需要花费很长时间,就好像它正在加载整个ShipRate
表一样。我哪里出错了
var query = (from order in db.Orders
join info in db.OrderInfo
on order.OrderId equals info.OrderId
join shipRate in db.ShipRate
on info.OrderId equals shipRate.OrderId
into sr
from shipRate in sr.DefaultIfEmpty()
where order.OrderId == orderId
select new
{
OrderId = order.OrderId,
OrderDetail = info.OrderDetail,
Carrier = shipRate.Carrier
}).SingleOrDefault();
使用正确的模型定义,您的查询如下:
var query = (from order in db.Orders
where order.OrderId == orderId
select new
{
OrderId = order.OrderId,
OrderDetail = order.OrderInfo.OrderDetail,
Carrier = order.OrderInfo.ShipRates.OrderBy(sr =>sr.CreateDate).FirstOrDefault()
}).SingleOrDefault();
但我不能确定,因为您没有提供示例数据和模型。塞廷·巴索兹的答案很好:理想情况下,您应该以允许使用导航属性的方式设置模型。如果您使用的是从数据库模式生成的模型,则通常意味着正确设置外键和主键
如果您不能做到这一点,您仍然可以通过编写如下SQL来获得类似的效果:
var query = (from order in db.Orders
where order.OrderId == orderId
let orderInfo = db.OrderInfo.FirstOrDefault(info => order.OrderId == info.OrderId)
let currentShipRate = db.ShipRate
.Where(shipRate => info.OrderId == shipRate.OrderId)
.OrderByDescending(shipRate => shipRate.CreateDate)
.FirstOrDefault()
select new
{
OrderId = order.OrderId,
OrderDetail = orderInfo.OrderDetail,
Carrier = currentShipRate.Carrier
}).SingleOrDefault();
然而,LINQtoSQL在构建高级查询方面远不如实体框架好,您描述的症状可能表明它实际上在进行多个数据库往返而不是连接。我建议通过调用查询上的.ToString()
,或者在LINQPad中执行查询并单击SQL选项卡,来记录您正在生成的查询(在.SingleOrDefault()之前)。这可能会为您提供查询行为不正常的原因的线索。在订单
和订单信息
之间似乎存在一对一的关系:每个订单正好有一个订单信息,每个订单信息正好是一个订单的信息,即外键OrderId引用的订单
另一方面,订单和运价之间似乎存在一对多的关系。每个订单都有零个或多个ShipRate,每个ShipRate都是恰好一个订单的ShipRate,即外键OrderId所指的订单
您需要“Orders”的多个属性,每个订单都有一个且唯一的OrderInfo及其零或多个发货率
当你有一对多关系时,你想要“有零或更多子项目的项目”,比如学校和学生,客户有他们的订单,或者在你的情况下:用他们的SHIPRATE订单,考虑使用一个超载的< /P>
在另一个方向:如果您想要一个项目及其外键引用的唯一其他项目,如他就读的学校的学生、创建订单的客户或其唯一订单信息,请使用Queryable.Join
我主要使用GroupJoin的重载,它有一个参数resultSelector,所以我可以选择我想要的属性
int orderId = ...
var ordersWithShipRates = dbContext.Orders.GroupJoin(dbContext.ShipRates,
order => order.Id, // from every Order take the primary key
shipRate => shipRate.OrderId, // from every ShipRate take the foreign key to Order
// parameter resultSelector: from every Order, with its zero or more ShipRates
// make one new
(order, shipRatesOfThisOrder) => new
{
// Select the Order properties that you plan to use:
Id = order.Id,
Date = order.Date,
...
ShipRates = shipRatesOfThisOrder.Select(shipRate => new
{
// Select the ShipRate properties that you plan to use:
Id = shipRate.Id,
Value = shipRate.Value,
...
})
.ToList(),
// A simple join to get the one and only OrderInfo
OrderInfo = dbContext.OrderInfos.Where(orderInfo => orderInfo.Id == order.Id)
.Select(orderInfo => new
{
// Select the orderInfo properties that you plan to use
Name = orderInfo.Name,
...
})
.FirstOrDefault(),
});
你能给出一些样本数据和模型吗。你的问题目前还不清楚。当数据库中有适当的关系时,linq查询很少需要联接。这是实体框架吗?LINQ到SQL?它是LINQ到SQL