2012-04-30 12 views
6

Utilizo Entity Framework 4.3 Code First y tengo problemas para actualizar las relaciones de muchos a muchos.No se pueden actualizar las relaciones de muchos a muchos en Entity Framework

que definen las siguientes clases:

public abstract class Entity 
{ 
    [Column(Order = 0)] 
    [Key] 
    public int Id { get; set; } 

    [Timestamp] 
    [Column(Order = 1)] 
    public byte[] Version { get; set; } 
} 


public class Video : Entity 
{ 
    public string Title { get; set; } 
    public string Description { get; set; } 
    public TimeSpan Length { get; set; } 

    public virtual ICollection<Coworker> Coworkers { get; set; } 
} 


public class Coworker : Entity 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public virtual ICollection<Video> Videos { get; set; } 
} 

Cuando se crea la base de datos, el aspecto esquema de la derecha: Hay una Vídeos, compañeros de trabajo y VideoCoworkers mesa también, sin

utilizo patrón de repositorio de una aplicación de n niveles acceder a la base de datos, mi método de inserción y actualización es el siguiente:

public T Insert(T entity) 
{ 
    //Creates database context. When it disposes, it calls context.SaveChanges() 
    using (var session = new DatabaseSession()) 
    { 
     session.Context.Set<T>().Add(entity); 
    } 
} 

public T Update(T entity) 
{ 
    //Creates database context. When it disposes, it calls context.SaveChanges() 
    using (var session = new DatabaseSession()) 
    { 
     entity = session.Context.Set<T>().Attach(entity); 
     session.Context.Entry(entity).State = EntityState.Modified; 
    } 
    return entity; 
} 

Cuando actualizo una entidad, que CR Eate el objeto de entidad desde un DTO, es por eso que usa DbSet.Attach en lugar de seleccionarlo y actualizar las propiedades una a una.

Cuando inicializar la base de datos, agrego algunos datos de prueba:

  1. crear 3 Compañeros de trabajo, donde hice nombre y apellido. (A, B, C)
  2. Crear 3 videos, donde establezco el título, la descripción y la longitud, y también establezco algunos compañeros de trabajo. El primer video tiene A, B, el segundo tiene B, C y el tercero tiene A, C.

Cuando enumero los videos de código, se puede ver que la colección Video.Coworkers está lleno de buenos valores, y cuando consulta la tabla de enlace (VideoCoworkers) en SQL Server Management Studio, también se ve bien.

Mi problema es cuando actualizo, por ejemplo, el título del video, funciona. Pero cuando intento eliminar de Video2 a los compañeros de trabajo existentes (B y C) y trato de agregar al compañero de trabajo A, la relación no se actualiza. Tampoco funciona cuando intento agregar un nuevo compañero de trabajo o solo intento eliminar uno. Creo la entidad que se usa como el parámetro del método Update() creando una nueva entidad Video con una nueva colección de Compañeros de Trabajo (que se seleccionan de la base de datos con el método Find() por Id).

¿Cuál es la forma correcta de actualizar las relaciones entre varios?

+0

No dice cómo elimina a los compañeros de trabajo de los videos, pero creo que debería recorrer la colección de videos de un compañero de trabajo y marcar los elementos que coincidan con sus DTO tal como se eliminaron. –

Respuesta

-1

Consulte primero here para ver cómo guardar detalles maestros en asp.net mvc con base de datos. Con suerte, le dará la idea sobre el código primero. También puede echar un vistazo a knokout.js ejemplo

+0

Gracias por su comentario, pero estos enlaces no ayudaron a resolver mi problema de actualización. – mrtx

+0

Vea este http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ – Tassadaque

+0

Gracias por su comentario nuevamente, pero mi problema está en el capa de acceso a datos, ni relacionada con MVC ni JS. En realidad, utilizo WebForms y WinForms, pero cada DTO transferida parece estar bien en ambos sentidos, por lo que parece, que no tiene nada que ver con el lado del cliente de la aplicación. – mrtx

6

Pero cuando intento eliminar de Vídeo2 los compañeros de trabajo existentes (B y C), y tratar de añadir un compañero de trabajo, entonces la relación no se actualiza.

Sin utilizar un repositorio genérico el procedimiento correcto sería:

using (var session = new DatabaseSession()) 
{ 
    video2 = session.Context.Set<Video>().Include(v => v.Coworkers) 
     .Single(v => v.Id == video2Id); 

    coworkerA = new Coworker { Id = coworkerAId }; 
    session.Context.Set<Coworker>().Attach(coworkerA); 

    video2.Coworkers.Clear(); 
    video2.Coworkers.Add(coworkerA) 

    session.Context.SaveChanges(); 
} 

La parte esencial es que se debe cargar o adjuntar la entidad en su estado original, cambie la entidad, es decir, eliminar y añadir los niños y luego guarda los cambios La detección de cambios de EF creará las instrucciones INSERT y DELETE necesarias para las entradas de la tabla de enlaces.El procedimiento simple para establecer el estado en Modified que está intentando en su método genérico Update es adecuado solo para actualizar las propiedades escalares, como cambiar el título del video, pero no funcionará para actualizar las relaciones entre las entidades.

2

Para resolver este problema:

  1. adjuntar a la entidad contexto
  2. carga de la colección (no se carga la colección, porque)
  3. cambiar el estado de entidad a
  4. cambios ahorrar modificados

Así que su código para la actualización debería ser así:

public Video Update(Video entity) 
{ 
    //Creates database context. When it disposes, it calls context.SaveChanges() 
    using (var session = new DatabaseSession()) 
    { 
     entity = session.Context.Set<Video>().Attach(entity); 
     session.Context.Entry(entity).Collection(p => p.Coworkers).Load(); 
     session.Context.Entry(entity).State = EntityState.Modified; 
    } 
    return entity; 
} 
Cuestiones relacionadas