2012-03-01 8 views
12

Si spera che sia una domanda molto semplice. Ma sto usando codice Prima con un app MVC e ho un oggetto Category e ServiceType che hanno una relazione molti a molti:Entity Framework 4 Non salvare le mie file Many-To-Many

public class Category 
{ 
    public Category() 
    { 
     ServiceTypes = new HashSet<ServiceType>(); 
    } 

    public Guid CategoryId { get; set; } 

    [Required(ErrorMessage = "Name is required")] 
    public string Name { get; set; } 

    public virtual ICollection<ServiceType> ServiceTypes { get; set; } 
} 

Il database è stato generato correttamente e contiene una tabella di collegamento denominata CategoryServiceTypes. Il mio problema è che aggiungo elementi alla mia raccolta ServiceTypes e chiamo il salvataggio e sebbene non si verifichi alcun errore, nessuna riga viene aggiunta a CategoryServiceTypes. Quando il codice qui sotto arriva a SaveChanges il conteggio sul category.ServiceTypes è 1, quindi qualcosa è sicuramente nella collezione:

[HttpPost] 
    public ActionResult Edit(Category category, Guid[] serviceTypeIds) 
    { 
     if (ModelState.IsValid) 
     { 
      // Clear existing ServiceTypes 
      category.ServiceTypes.Clear(); 

      // Add checked ServiceTypes 
      foreach (Guid serviceType in serviceTypeIds) 
      { 
       ServiceType st = db.ServiceTypes.Find(serviceType); 
       category.ServiceTypes.Add(st); 
      } 

      db.Entry(category).State = EntityState.Modified; 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     return View(category); 
    } 

spero che sto facendo qualcosa di sbagliato qui, ovviamente. Qualche idea?

Grazie.

EDIT:

Anche se la risposta al di sotto è infatti la risposta corretta ho pensato di aggiungere la seguente versione definitiva del metodo Modifica Messaggio:

[HttpPost] 
    public ActionResult Edit(Category category, Guid[] serviceTypeIds) 
    { 
     if (ModelState.IsValid) 
     { 
      // Must set to modified or adding child records does not set to modified 
      db.Entry(category).State = EntityState.Modified; 

      // Force loading of ServiceTypes collection due to lazy loading 
      db.Entry(category).Collection(st => st.ServiceTypes).Load(); 

      // Clear existing ServiceTypes 
      category.ServiceTypes.Clear(); 

      // Set checked ServiceTypes 
      if (serviceTypeIds != null) 
      { 
       foreach (Guid serviceType in serviceTypeIds) 
       { 
        ServiceType st = db.ServiceTypes.Find(serviceType); 
        category.ServiceTypes.Add(st); 
       } 
      } 

      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     return View(category); 
    } 

avviso la linea che costringe il caricamento di la raccolta ServiceTypes, è necessaria poiché il caricamento lento non include quegli elementi secondari, il che significa che la raccolta ServiceTypes non è stata eseguita.

risposta

8

Provare a spostare la linea in cui si allega la categoria al contesto di fronte al ciclo:

[HttpPost] 
public ActionResult Edit(Category category, Guid[] serviceTypeIds) 
{ 
    if (ModelState.IsValid) 
    { 
     // Clear existing ServiceTypes 
     category.ServiceTypes.Clear(); 
     db.Entry(category).State = EntityState.Modified; 
     // category attached now, state Modified 

     // Add checked ServiceTypes 
     foreach (Guid serviceType in serviceTypeIds) 
     { 
      ServiceType st = db.ServiceTypes.Find(serviceType); 
      // st attached now, state Unchanged 
      category.ServiceTypes.Add(st); 
      // EF will detect this as a change of category and create SQL 
      // to add rows to the link table when you call SaveChanges 
     } 

     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    return View(category); 
} 

Nel EF codice non ci si accorge di aver aggiunto i tipi dei servizi, perché si collega la categoria il contesto in cui i tipi di servizio sono già nella raccolta category.ServiceTypes e tutti i tipi di servizio sono già associati al contesto nello stato Unchanged.

+0

Grazie Slauma, questo era esattamente il problema. – Gary

+0

Sebbene la tua risposta ora salvi correttamente le voci nel database, trovo che quando viene immesso il metodo Edit httppost, il conteggio category.ServiceTypes è 0, anche se nel metodo di risposta Edit contiene sicuramente 1 ServiceType salvato. Qualche idea su cosa lo sta causando? – Gary

+0

@Gary: questo sarebbe un problema con il modelbinder MVC. Per me sembra che non importi davvero se 'category.ServiceTypes' contiene qualcosa perché la prima cosa che stai facendo è cancellare comunque quella lista. Importante è solo la raccolta 'Guid [] serviceTypeIds' perché stai caricando ServiceType dal DB con' Find' usando quegli Id e poi crei l'associazione con l'entità caricata. – Slauma

Problemi correlati