2012-03-01 11 views
12

Esperemos que sea una pregunta muy simple. Pero estoy utilizando código de Primera con una aplicación MVC y tengo una categoría y ServiceType objeto que tiene una relación de muchos a muchos:Entity Framework 4 No guarde mis filas 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; } 
} 

La base de datos se ha generado correctamente y contiene una tabla de vinculación denominado CategoryServiceTypes. Mi problema es agregar elementos a mi colección de tipos de servicios y guardar llamadas y, aunque no se produce ningún error, no se agregan filas a CategoryServiceTypes. Cuando el código de abajo llega a SaveChanges el recuento de category.ServiceTypes es 1, por lo que algo está definitivamente en la colección:

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

espero que estoy haciendo algo mal aquí, obviamente. ¿Algunas ideas?

Gracias.

EDIT:

Aunque la respuesta de abajo es de hecho la respuesta correcta pensé que me gustaría añadir lo siguiente versión final del método Editar mensaje:

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

Aviso de la línea que obliga a la carga de la colección ServiceTypes, esto es necesario ya que la carga diferida no incluye esos elementos secundarios, lo que significa que borrar la colección ServiceTypes no hizo nada.

Respuesta

8

intenta mover la línea donde se conectan la categoría al contexto en el frontal del bucle:

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

En su código de EF no se da cuenta de que ha añadido los servicetypes porque usted añade a la categoría el contexto cuando los tipos de servicios ya están en la colección category.ServiceTypes y todos los tipos de servicios ya están adjuntos al contexto en el estado Unchanged.

+0

Gracias Slauma, ese era exactamente el problema. – Gary

+0

Aunque su respuesta ahora guarda correctamente las entradas en la base de datos, descubro que cuando se ingresa el método Edit httppost, el recuento de categoría.ServiciosTypes es 0, aunque en el método de respuesta Edit contiene definitivamente 1 ServiceType guardado. ¿Alguna idea de lo que está causando eso? – Gary

+0

@Gary: Este sería un problema de encuadernador MVC. Para mí, parece que no importa si 'category.ServiceTypes' contiene algo porque lo primero que haces es borrar esa lista de todos modos. Importante es solo la colección 'Guid [] serviceTypeIds' porque está cargando el ServiceType del DB con' Find' usando esos Id y luego crea la asociación con la entidad cargada. – Slauma

Cuestiones relacionadas