Я вижу что-то странное в вашем Присоединении.
Каждый ордер имеет код. Каждый OrderDetail имеет Order, который также имеет код.
Если существует отношение один-ко-многим между Orders и OrderDetails, то каждый Order имеет ноль или более OrderDetails. Каждый OrderDetail принадлежит ровно одному Order, а именно Order, на который указывает внешний ключ. Это тот же Order, что и OrderDetail.Order?
В этом случае Order.Code равен OrderDetail.Order.Code для каждого OrderDetail этого кода. Не очень полезно выполнять объединение этих значений.
Я думаю, что вы имеете в виду объединение по первичному ключу и внешнему ключу.
В любом случае, независимо от того, присоединяетесь ли вы к ключам или коду свойства, решение вашей проблемы - выполнить GroupJoin вместо Join.
Если вы следовали первым соглашениям кода структуры сущностей *1014*, у вас будет что-то похожее на это:
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;}
}
Возможно, вы использовали разные идентификаторы для своих свойств, но главное - это виртуальные свойства.
В структуре сущностей не виртуальные свойства представляют столбцы в В таблице виртуальные свойства представляют отношения между таблицами (один ко многим, многие ко многим).
Требование
От каждого заказа, дайте мне некоторые свойства, вместе с некоторыми свойствами OrderDetail с минимальной 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
Если вы используете платформу сущностей и вам нужно выберите «Все заказы с его OrderDetails», «Все школы с его учащимися», «Все продукты с его компонентами», фактически: все элементы вместе со всеми связанными подпунктами, как правило, проще использовать ICollections вместо выполнения a само присоединение:
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-) соединения? Entity Framework знает ваши отношения и выполняет правильное соединение для вас с правильными (внешними) ключами.
На самом деле, я редко создаю само себя. Большую часть времени я использую виртуальные свойства.