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。大多数时候我使用虚拟属性。