Entity Framework 5 Идентификация отношений с использованием кода Сначала генерируется исключение InvalidOperationException

Я получаю следующее InvalidOperationException:

Изменения в базе данных были успешно зафиксированы, но при обновлении контекста объекта произошла ошибка. ObjectContext может быть в несовместимом состоянии. Внутреннее сообщение об исключении: Произошло нарушение ограничения ссылочной целостности: Значения свойств, которые определяют ссылочные ограничения, не согласованы между основным и зависимыми объектами в отношении.

Это происходит, когда я запускаю следующий код (обратите внимание, где я вызываю Clear() для коллекции ShipDates, а затем добавляю новые экземпляры):

// get or create the order
Order order = null;
if (vm.OrderNumber > 0)
    order = GetOrder(vm.OrderNumber);
else
    order = new Order(orderDate: DateTime.Now, isClosed: false, brokerNum: broker.BrokerNumber);

// get or create the order page
OrderPage orderPage = null;
bool bIsExistingPage = vm.PageNumber > 0;
if (bIsExistingPage)
    orderPage = order.OrderPages.First(op => op.PageNumber == vm.PageNumber);
else 
    orderPage = new OrderPage(vm.VendorNumber, vm.BulletinNumber, 1, DateTime.Now, order);

// merge changes or create the order page items
foreach (var opi in vm.OrderPageItems)
{
    var orderPageItem = orderPage.OrderPageItems.FirstOrDefault(xopi => 
                                                    xopi.StoreNumber == opi.StoreNumber &&
                                                    xopi.ItemNumber == opi.ItemNumber);
    if (orderPageItem == null)
    {
        orderPageItem = new OrderPageItem(
                                vendorNum: vm.VendorNumber,
                                bullNum: vm.BulletinNumber,
                                itemNum: opi.ItemNumber,
                                storeNum: opi.StoreNumber,
                                quantity: opi.Quantity,
                                orderPage: orderPage);
        orderPage.OrderPageItems.Add(orderPageItem);
    }
    else
    {
        orderPageItem.Quantity = opi.Quantity;
    }
}

// clear out the old ship dates if any
orderPage.ShipDates.Clear();

// reset the ship dates
vm.ShipDates.ForEach(date => orderPage.ShipDates.Add(new OrderPageShipDate(date, orderPage)));

if (!bIsExistingPage)
    order.OrderPages.Add(orderPage);

_context.AddOrUpdate(order);
_context.SaveChanges();

result.OrderNumber = order.OrderNumber;
result.OrderDate = order.OrderDate;

Вот соответствующие части двух классов, участвующих в идентификации отношений:

/// <summary>
/// This class represents a a set of items added to an order from a particular bulletin at a particular time.
/// </summary>
[ScaffoldTable(true)]
public class OrderPage : IEntity, IAuditInfo
{       
    #region Construction
    //...
    #endregion

    #region IEntity Members
    /// <summary>
    /// The unique identifier for an order item.
    /// </summary>
    [Key]
    public virtual int Id { get; set; }
    #endregion

    // other properties...

    public virtual ICollection<OrderPageShipDate> ShipDates { get; private set; }
}

А также:

/// <summary>
/// This class represents a shipping date for an order page that has been added to an order.
/// </summary>
[ScaffoldTable(true)]
public class OrderPageShipDate : IEntity
{
    #region Construction
    // ...
    #endregion

    #region IEntity Members
    /// <summary>
    /// The unique identifier for an order item.
    /// </summary>
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), Column(Order = 2)]
    public virtual int Id { get; set; }
    #endregion

    public virtual DateTime ShipDate { get; private set; }

    [Key, ForeignKey("OrderPage"), Column(Order = 1)]
    public virtual int OrderPageId { get; private set; }

    public virtual OrderPage OrderPage { get; private set; }
}

Ошибка возникает в SaveChanges(), если у меня есть существующий OrderPage, который я изменяю. Я хочу, чтобы OrderPage отбрасывал все существующие OrderPageShipDates в коллекции ShipDates и добавлял их обратно в новых экземплярах.

Можете ли вы помочь мне понять это? Заранее спасибо.

О, ответ ниже - я явно загружаю даты доставки в вызове GetOrder(). Вот этот код:

[NonAction]
private Order GetOrder(int orderNumber)
{
    var user = _context.Users.SingleOrDefault(u => u.Username == User.Identity.Name);
    var roles = _roleProvider.GetRolesForUser(User.Identity.Name).ToList();

    var broker = user as Broker;
    order = _context.Orders
        .Where(o => o.BrokerNumber == broker.BrokerNumber && o.OrderNumber == orderNumber)
        .Include(o => o.OrderPages)
        .Include(o => o.OrderPages.Select(op => op.OrderPageItems))
        .Include(o => o.OrderPages.Select(op => op.ShipDates))
        .SingleOrDefault();

    return order;
} 

1 ответ

Решение

Хорошо, я нашел ответ или ответы.

Во-первых, я пытался сделать слишком много, прежде чем _context.SaveOrUpdate(), Мне нужно было получить идентификатор из БД для моего OrderPage прежде чем я добавил свой OrderPageShipDates, поскольку их составные ключи зависят от "реального" OrderPageId, Так я звоню _context.SaveOrUpdate() прежде чем добавить их сейчас, что дает мне "реальный" Id.

Во-вторых, я неправильно реализовал _context.AddOrUpdate() логика. Он делал только Add. Многие эффекты просачивались, но самым большим было изменение основного идентификатора (он был добавлен снова, а не обновлен).

Еще раз спасибо за ваши усилия!

Другие вопросы по тегам