2012-04-05 16 views
5

Ho dato un'occhiata ad alcune delle risposte a domande simili e non sembrano corrispondere alle mie.Aggiunta di un nuovo oggetto figlio mentre si modifica l'Entity Framework esistente per i bambini

Sto cercando di incorporare un modello da Entity Framework: DbContext (pagina 90) e non sembra funzionare. Il codice che sto utilizzando è il seguente:

[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); 

} 

Ho corso un esempio in cui l'oggetto Ordine ha due oggetti OrderDetail esistenti e sto cercando di aggiungere un terzo. Ho incluso la variabileOrderDetailId aggiunta, in modo da poterla aggiungere al 'Watch' e vedere quando è stata modificata

Quello che ho trovato sta accadendo è l'OrderId dell'oggetto OrderDetail aggiunto (che è 0 quando il ciclo foreach è inserito) viene aggiornato dalla struttura dell'entità al OrderId dell'oggetto Order. Ciò avviene dopo la prima iterazione attraverso il ciclo foreach (quando la prima entità figlio ha il suo stato modificato in modificato. Ciò significa che tutti e tre i bambini vengono contrassegnati come modificati. Ciò sta facendo sì che SaveChanges() tenti di aggiornare una voce nel database che non esiste

Se qualcun altro ha avuto questo problema, allora sarei grato per qualsiasi consiglio su come aggirare questo. Dovrò anche affrontare gli oggetti figlio esistenti che vengono eliminati, ma io non hanno ancora ottenuto intorno a questo, quindi se qualcuno sa di un modello per questo, che sarebbe anche apprezzato

Edit:.

Dopo aver preso il consiglio di Slauma e la rimozione db.Or ders.Add (ordine). Sono stato in grado di spostare la chiamata a db.Entry (order) .State sotto il ciclo foreach. Ciò mi ha permesso di scorrere il ciclo e impostare lo stato di ogni oggetto OrderDetail da modificare per quelli esistenti e aggiunto per quello aggiunto. Ho quindi dovuto semplicemente assegnare l'OrderId del genitore al OrderId del bambino e l'aggiornamento è andato a buon fine. Ho anche incluso il codice che ho usato per eliminare oggetti figlio durante la modifica. Non sono sicuro di quanto sia efficiente, ma funziona. Ecco il codice rivisto:

[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); 
    } 
+0

Grazie per la domanda. In realtà il tuo codice mi ha aiutato a darmi una soluzione semplice per aggiornare o inserire i figli di un'entità. Taglia e incolla, ha funzionato la prima volta, fatto il lavoro. +1 –

risposta

1

rimuovere questa riga dal codice:

db.Orders.Add(order); 

Questo effettivamente mettere l'ordine compresi tutti OrderDetails in Added Stato. La correzione delle relazioni (che avviene automaticamente in Add) imposta il valore OrderId di allOrderDetails alla chiave dell'ordine. Quando si inserisce il ciclo orderDetail.OrderId è != 0 per tutti gli elementi di dettaglio e si immette sempre il ramo che imposta lo stato su Modified. Nessun articolo orderDetail è nello stato Added quando il ciclo è terminato.

+0

Ciao Slauma, grazie per la risposta. Se rimuovo la riga db.Orders.Add (ordine), la chiamata che modifica lo stato dell'entità Ordine da modificare causa una violazione dell'integrità referenziale prima che il codice raggiunga anche il ciclo foreach. La tua risposta mi ha comunque permesso di provare un approccio diverso che funziona, che inserirò in una modifica alla mia domanda originale. – MickySmig

Problemi correlati