5

私は同様の質問に対する答えのいくつかを見てきましたが、それらは実際には私のものに合わないようです。

Entity Framework:DbContext(90ページ)のパターンを取り込もうとしていますが、機能しないようです。私が使用しているコードを以下に示します。

[HttpPost]
public ActionResult Edit(Order order)
{
     if (ModelState.IsValid)
     {
         db.Orders.Add(order);
         db.Entry(order).State = EntityState.Modified;

         foreach (var orderDetail in order.OrderDetails)
         {
              if (orderDetail.OrderId == 0)
              {
                  db.Entry(orderDetail).State = EntityState.Added;
              }
              else
              {
                  db.Entry(orderDetail).State = EntityState.Modified;
              }
              // The example order that I'm updating has two child entities
              // so this orderId will be for the third, added one.
              int addedOrderDetailId = order.OrderDetails[2].OrderId;
          }
          db.SaveChanges();
          return RedirectToAction("Index");
     }

     ViewBag.CustomerId = new SelectList(db.Customers, "CustomerId", "CompanyName", order.CustomerId);

     return View(order);

}

Orderオブジェクトに2つの既存のOrderDetailオブジェクトがあり、3つ目を追加しようとしている例を実行しています。addOrderDetailId変数を含めたので、それを「ウォッチ」に追加して、いつ変更されたかを確認できます。

私が見つけたのは、追加されたOrderDetailオブジェクトのOrderId(foreachループに入ると0)がエンティティフレームワークによってOrderオブジェクトのOrderIdに更新されていることです。これは、foreachループの最初の反復後(最初の子エンティティの状態が変更済みに変更されているとき。これは、3つの子すべてが変更済みとしてマークされていることを意味します。これにより、SaveChanges()がエントリを更新しようとします。存在しないデータベースに。

他の誰かがこの問題を抱えているなら、私はこれを回避するためのアドバイスをいただければ幸いです。削除される既存の子オブジェクトにも対処する必要がありますが、まだこれに慣れていないので、誰かがこれのパターンを知っているなら、それもありがたいです。

編集:

Slaumaのアドバイスを受けて、db.Orders.Add(order)を削除した後。foreachループの下にあるdb.Entry(order).Stateへの呼び出しを移動することができました。これにより、ループをループして、各OrderDetailオブジェクトの状態を既存のオブジェクト用に変更し、追加したオブジェクト用に追加することができました。次に、親のOrderIdを子のOrderIdに割り当てるだけで、更新が成功しました。編集中に子オブジェクトを削除するために使用したコードも含めました。これがどれほど効率的かはわかりませんが、機能します。改訂されたコードは次のとおりです。

    [HttpPost]
    public ActionResult Edit(Order order)
    {
        if (ModelState.IsValid)
        {
            List<int> previousProductIds = db.OrderDetails
                .Where(ep => ep.OrderId == order.OrderId)
                .Select(ep => ep.ProductId)
                .ToList();

            List<int> currentProductIds = order.OrderDetails
                .Select(o => o.ProductId)
                .ToList();

            List<int> deletedProductIds = previousProductIds
                .Except(currentProductIds).ToList();


            foreach (var deletedProductId in deletedProductIds)
            {
                OrderDetail deletedOrderDetail = db.OrderDetails
                    .Where(od => od.OrderId == order.OrderId && od.ProductId == deletedProductId)
                    .Single();

                db.Entry(deletedOrderDetail).State = EntityState.Deleted;
            }

            foreach (var orderDetail in order.OrderDetails)
            {
                if (orderDetail.OrderId == 0)
                {
                    db.Entry(orderDetail).State = EntityState.Added;
                    orderDetail.OrderId = order.OrderId;
                }
                else
                {
                    db.Entry(orderDetail).State = EntityState.Modified;
                }
            }
            db.Entry(order).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.CustomerId = new SelectList(db.Customers, "CustomerId", "CompanyName", order.CustomerId);
        return View(order);
    }
4

1 に答える 1

1

コードから次の行を削除します。

db.Orders.Add(order);

これにより、実際にはすべてのorderDetailsを含む注文がAdded状態になります。関係の修正(で自動的に行われますAdd)はOrderIdすべて OrderDetailsのを注文のキーに設定します。ループに入ると、すべての詳細アイテムが対象になり、常に状態をに設定するブランチに入りorderDetail.OrderIdます。ループが終了すると、orderDetailアイテムはもう状態になりません。!= 0ModifiedAdded

于 2012-04-05T15:23:19.023 に答える