Select 行在连接查询中具有最短日期
Select rows with minumum date in join query
我正在使用 entity Framework 和 LINQ 两者执行这两个表之间的连接:
var query =
orders.Join(
orderdetails,
order => order.Code,
orderdt => orderdt.Order.Code,
(order, orderdt)
=> new
{
Code = order.Code,
WarehouseDivision = orderdt.WarehouseDivision,
Type = order.Type,
SupplierCode = order.SupplierCode,
SupplierDescription = order.SupplierDescription,
ExpectedDeliveryDate = orderdt.ExpectedDeliveryDate
});
连接工作正常。
现在对于每个连接行,我需要 select 具有最小预期交货日期的行。
关于如何实现这一目标的任何提示?
我在你的加入中看到一些奇怪的东西。
每个订单都有一个代码。每个 OrderDetail 都有一个 Order,它也有一个 Code。
如果Orders和OrderDetails是一对多的关系,那么每个Order都有零个或多个OrderDetails。每个OrderDetail恰好属于一个Order,即外键指向的Order。这与 OrderDetail.Order 的顺序相同吗?
在这种情况下,Order.Code 等于 OrderDetail.Order。此代码的每个 OrderDetail 的代码。对这些值执行联接不是很有用。
我认为你的意思是加入主键和外键。
无论哪种方式,无论您是通过键还是通过 属性 代码加入,您的问题的解决方案是执行 GroupJoin 而不是 Join。
如果您遵循了 entity framework code first conventions,您将得到类似的内容:
class Order
{
public int Id {get; set;} // Primary key
... // other Order properties
// every Order has zero or more OrderDetails (one-to-many)
public virtual ICollection<OrderDetail> OrderDetails {get; set;}
}
class OrderDetail
{
public int Id {get; set;}
public DateTime ExpectedDeliveryDate {get; set;}
... // other OrderDetail properties
// every OrderDetail belongs to exactly one Order, using foreign key
public int OrderId {get; set;}
public virtual Order Order {get; set;}
}
可能是您为您的财产使用了不同的标识符,但主要是虚拟财产。
In entity framework the non-virtual properties represent the columns in the table, the virtual properties represent the relations between the tables (one-to-many, many-to-many).
要求
From every Order, give me some properties, together with some properties of the OrderDetail with the minimum ExpectedDeliveryDate.
GroupJoin 的解决方案
主键/外键上的 GroupJoin:
var OrdersWithOldestOrderDetail = dbContext.Orders // GroupJoin Orders
.GroupJoin(dbContext.OrderDetails, // with OrderDetails
order => order.Id, // from every Order take the Id
orderDetail => orderDetail.OrderId, // from every OrderDetail take the OrderId
(order, orderDetailsOfThisOrder) => new // take the Order with all its matchin OrderDetails
{ // to make one new
// Select the Order properties that you plan to use:
...
// Select the OrderDetail with the minimum ExpectedDeliveryDate
// To do this, order by ascending deliveryDate
// then Select the properties you want to used
// and take the FirstOrDefault
EarliestDeliveredOrderDetail = orderDetailsOfThisOrder
.OrderBy(orderDetail => orderDetail.ExpectedDeliveryDate)
.Select(orderDetail => new
{
...
})
.ToList(),
});
如果您真的想加入您所说的属性:
var result = dbContext.Orders // GroupJoin Orders
.GroupJoin(dbContext.OrderDetails, // with OrderDetails
order => order.Code, // from every Order take the Code
orderDetail => orderDetail.Order.Code, // from every OrderDetail take Order.Code
(order, orderDetailsWithThisCode) => new // take the Order with all its matchin OrderDetails
{
... etc, same as above
使用 ICollection 的更简单的解决方案
如果您正在使用 entity framework 并且您需要 select "All orders with its OrderDetails"、"All Schools with its Students"、"All Products with its Components",事实上:所有项目以及所有相关子项,通常使用 ICollections 比自己执行连接更简单:
var OrdersWithOrderDetails = dbContext.Orders.Select(order => new
{
// Select the Order properties that you plan to use:
...
EarliestDeliveredOrderDetail = order.OrderDetails
.OrderBy(orderDetail => orderDetail.ExpectedDeliveryDate)
.Select(orderDetail => new
{
// Select the OrderDetail properties that you plan to use:
...
})
.FirstOrDefault(),
})
看看使用 ICollections 而不是 (Group-)join 时感觉有多自然? Entity framework 了解您的关系并使用正确的(外)键为您执行正确的连接。
其实我自己很少创建Join。大多数时候我使用虚拟属性。
我正在使用 entity Framework 和 LINQ 两者执行这两个表之间的连接:
var query =
orders.Join(
orderdetails,
order => order.Code,
orderdt => orderdt.Order.Code,
(order, orderdt)
=> new
{
Code = order.Code,
WarehouseDivision = orderdt.WarehouseDivision,
Type = order.Type,
SupplierCode = order.SupplierCode,
SupplierDescription = order.SupplierDescription,
ExpectedDeliveryDate = orderdt.ExpectedDeliveryDate
});
连接工作正常。 现在对于每个连接行,我需要 select 具有最小预期交货日期的行。 关于如何实现这一目标的任何提示?
我在你的加入中看到一些奇怪的东西。
每个订单都有一个代码。每个 OrderDetail 都有一个 Order,它也有一个 Code。
如果Orders和OrderDetails是一对多的关系,那么每个Order都有零个或多个OrderDetails。每个OrderDetail恰好属于一个Order,即外键指向的Order。这与 OrderDetail.Order 的顺序相同吗?
在这种情况下,Order.Code 等于 OrderDetail.Order。此代码的每个 OrderDetail 的代码。对这些值执行联接不是很有用。
我认为你的意思是加入主键和外键。
无论哪种方式,无论您是通过键还是通过 属性 代码加入,您的问题的解决方案是执行 GroupJoin 而不是 Join。
如果您遵循了 entity framework code first conventions,您将得到类似的内容:
class Order
{
public int Id {get; set;} // Primary key
... // other Order properties
// every Order has zero or more OrderDetails (one-to-many)
public virtual ICollection<OrderDetail> OrderDetails {get; set;}
}
class OrderDetail
{
public int Id {get; set;}
public DateTime ExpectedDeliveryDate {get; set;}
... // other OrderDetail properties
// every OrderDetail belongs to exactly one Order, using foreign key
public int OrderId {get; set;}
public virtual Order Order {get; set;}
}
可能是您为您的财产使用了不同的标识符,但主要是虚拟财产。
In entity framework the non-virtual properties represent the columns in the table, the virtual properties represent the relations between the tables (one-to-many, many-to-many).
要求
From every Order, give me some properties, together with some properties of the OrderDetail with the minimum ExpectedDeliveryDate.
GroupJoin 的解决方案
主键/外键上的 GroupJoin:
var OrdersWithOldestOrderDetail = dbContext.Orders // GroupJoin Orders
.GroupJoin(dbContext.OrderDetails, // with OrderDetails
order => order.Id, // from every Order take the Id
orderDetail => orderDetail.OrderId, // from every OrderDetail take the OrderId
(order, orderDetailsOfThisOrder) => new // take the Order with all its matchin OrderDetails
{ // to make one new
// Select the Order properties that you plan to use:
...
// Select the OrderDetail with the minimum ExpectedDeliveryDate
// To do this, order by ascending deliveryDate
// then Select the properties you want to used
// and take the FirstOrDefault
EarliestDeliveredOrderDetail = orderDetailsOfThisOrder
.OrderBy(orderDetail => orderDetail.ExpectedDeliveryDate)
.Select(orderDetail => new
{
...
})
.ToList(),
});
如果您真的想加入您所说的属性:
var result = dbContext.Orders // GroupJoin Orders
.GroupJoin(dbContext.OrderDetails, // with OrderDetails
order => order.Code, // from every Order take the Code
orderDetail => orderDetail.Order.Code, // from every OrderDetail take Order.Code
(order, orderDetailsWithThisCode) => new // take the Order with all its matchin OrderDetails
{
... etc, same as above
使用 ICollection 的更简单的解决方案
如果您正在使用 entity framework 并且您需要 select "All orders with its OrderDetails"、"All Schools with its Students"、"All Products with its Components",事实上:所有项目以及所有相关子项,通常使用 ICollections 比自己执行连接更简单:
var OrdersWithOrderDetails = dbContext.Orders.Select(order => new
{
// Select the Order properties that you plan to use:
...
EarliestDeliveredOrderDetail = order.OrderDetails
.OrderBy(orderDetail => orderDetail.ExpectedDeliveryDate)
.Select(orderDetail => new
{
// Select the OrderDetail properties that you plan to use:
...
})
.FirstOrDefault(),
})
看看使用 ICollections 而不是 (Group-)join 时感觉有多自然? Entity framework 了解您的关系并使用正确的(外)键为您执行正确的连接。
其实我自己很少创建Join。大多数时候我使用虚拟属性。