0

次の InvalidOperationException が発生します。

データベースへの変更は正常にコミットされましたが、オブジェクト コンテキストの更新中にエラーが発生しました。ObjectContext が矛盾した状態にある可能性があります。内部例外メッセージ: 参照整合性制約違反が発生しました: 参照制約を定義するプロパティ値が、リレーションシップ内のプリンシパル オブジェクトと依存オブジェクトの間で一貫していません。

これは、次のコードを実行すると発生します (ShipDates コレクションで Clear() を呼び出し、新しいインスタンスを追加する場所に注意してください)。

// 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;

以下は、識別関係に関与する 2 つのクラスの関連部分です。

/// <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; }
}

変更中の既存の OrderPage がある場合、SaveChanges() でエラーが発生します。OrderPage で、ShipDates コレクション内の既存のすべての OrderPageShipDates を削除し、新しいインスタンスに追加し直す必要があります。

これを理解するのを手伝ってもらえますか? 前もって感謝します。

ああ、以下の応答について - 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;
} 
4

1 に答える 1

0

わかりました、答えが見つかりました。

まず、以前はやりすぎていました_context.SaveOrUpdate()。複合キーは 'real' に依存するため、OrderPageを追加する前にDB から Id を取得する必要がありました。したがって、それらを追加する前に呼び出して、「実際の」IDを取得します。OrderPageShipDateOrderPageId_context.SaveOrUpdate()

_context.AddOrUpdate()第二に、ロジックの実装を誤っていました。追加のみを行っていました。多くのトリクル ダウン効果がありますが、最大のものはプリンシパル ID が変更されたことです (更新される代わりに再度追加されました)。

あなたの努力に再び感謝します!

于 2013-09-25T15:28:32.053 に答える