2011-12-08 36 views
8

Tengo un proyecto MVC y el uso de Entity Framework Code First y objetos POCO para la base de datos. Por ejemplo:Cómo actualizar entidades relacionadas en Entity Framework

public class ClassA 
{ 
    public int? Id {get; set;} 
    public string Name { get; set;} 
    public virtual ClassB B {get; set;} 
} 

public class ClassB 
{ 
    public int? Id {get;set;} 
    public string Description {get;set;} 
} 

Tengo un ActionResult que crea o edita un modelo. El problema es cuando llamo a este ActionResult para actualizar el modelo y se ha cambiado model.B, la relación no se guarda en la base de datos. Cuando se llama a ActionResult para crear un nuevo objeto, funciona como se esperaba. ¿Cómo puedo solucionar esto?

public ActionResult Save(ClassA model) 
{ 
    model.B = GetBFromDb(model.B.Id.Value); 

    if(ModelState.IsValid) 
    { 
    if (id.HasValue) 
    { 
     context.Entry(model).State = System.Data.EntityState.Modified; 
    } 
    else 
    { 
     context.ClassAs.Add(model); 
    } 
    context.SaveChanges(); 
    // redirect to index etc. 
    } 
    return View("EditForm", model); 
} 

Respuesta

3

Lo resuelto cambiando ClassA con una clave externa a ClassB, y establecer el valor de BId:

public class ClassA 
{ 
    public int? Id {get; set;} 
    public string Name { get; set;} 
    public int BId {get;set;} // foreign key to B 
    public virtual ClassB B {get; set;} 
} 

¿Por qué esta propiedad clave externa hace el trabajo en lugar de la ky extranjera generada de EF?

+3

en desconectado, cuando no tiene una clave externa, hay algunas lagunas que EF no puede solucionar y tiene que probar código adicional. De lo contrario, no puede ver la relación. Con la propiedad FK, es un valor escalar y más fácil para EF realizar un seguimiento de los procesos. De hecho, escribí mi columna de puntos de datos de enero de 2012 sobre este tema exacto. EF es mucho más fácil de usar cuando tienes una propiedad escalar FK. De lo contrario, muchas funciones que usted espera "solo funcionan" no pueden y le obligan a tener una mejor comprensión de lo que está sucediendo y cómo proporcionar la información necesaria. Lo siento, no he visto el FK faltante antes de –

+0

@JulieLerman, no hay problema, gracias por su ayuda! :) – Marthijn

2

No se le puede llamar:

context.Entry(model).State = System.Data.EntityState.Modified; 

La entidad tiene que ser recuperada a partir del contexto primero para que pueda comenzar el seguimiento de EF ella. Luego, deberá aplicar los cambios a esa entidad antes de llamar al context.SaveChanges().

var entity = context.ClassAs.Find(model.Id); 

// set properties you want to modify on entity 
entity.Name = model.Name; 
entity.ClassB = context.ClassBs.Find(model.ClassB.Id); 
// other changes to entity as required... 

context.SaveChanges(); 

De esta manera EF es el seguimiento de entity y sabe aplicar una actualización en contra de ella.

+0

¡Gracias esto funciona! ¿Y cómo configuro 'entity.ClassB = null;'? Parece que establecerlo en null no funciona. – Marthijn

+1

Yuck ... context.Entry (model) .State hará que el contexto vea si se está rastreando el modelo y, de lo contrario, comenzará a rastrearlo. No es necesario ejecutar otra consulta db para rastrear la instancia del modelo. El problema que está teniendo Henkie con esa ocde es que la entrada que ese método solo cambiará establecerá el estado de la entidad que se transfiere. La configuración de estado "modificado" no se aplicará al resto del gráfico. –

+0

@JulieLerman Gracias he encontrado algunos tutoriales que también configuran el estado para modificar. Pero aún tengo el problema de que mis relaciones no se actualizarán. – Marthijn

0

Si adjunta y luego establece el estado al marco de la entidad modificada enviará todas las propiedades para la actualización. No tiene que tomar el enfoque de nutria aquí a continuación ya que causa una carga separada completa. Si lo haces de esa manera, no tiene sentido pasar un modelo, solo una identificación y luego llamas a TryUpdateModel para completar las propiedades del formulario.

personalmente el pegado modificado aquí es un poco más limpio, ya que no requiere una ida y vuelta completa, debido a la carga de datos

http://geekswithblogs.net/michelotti/archive/2009/11/27/attaching-modified-entities-in-ef-4.aspx

Cuestiones relacionadas