2013-09-23 1 views
0

Я получаю следующее InvalidOperationException:Entity Framework 5 Определения отношений с помощью Code First бросков 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; 
} 
+0

Я ожидаю, что явная загрузка «orderPage.ShipDates» перед их очисткой решит проблему, но ваш код имеет несколько путей выполнения, поэтому трудно сказать. –

+0

Я явно загружаю их в вызов GetOrder(). Вот этот код: – jlavallet

+0

Если кто-то еще может мне помочь, обратите внимание, что я добавил код в конце моего исходного сообщения. Благодарю. – jlavallet

ответ

0

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

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

Во-вторых, я неправильно реализовал логику _context.AddOrUpdate(). Это делало только Add. Лоты эффектов стекания, но самый большой был Идентификатор Принципала (он был добавлен снова вместо того, чтобы быть обновленным).

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

Смежные вопросы