c# - propiedad - La relación entre los dos objetos no se puede definir porque están unidos a diferentes objetos ObjectContext
matrices en c# windows form (2)
He leído algunas preguntas / respuestas que tienen que ver con este mensaje de error en particular, pero no entiendo muy bien la solución adecuada.
He leído muchas veces que debe crear el contexto EF4, usarlo y luego deshacerse de él. A lo largo de mi aplicación, estoy cargando entidades aquí y allá usando diferentes objetos de contexto, y luego eventualmente quiero asociar las entidades.
Creé una aplicación de consola simple que causa el error fácilmente. El modelo muy simple está diagramado seguido por el código.
¿Cómo puedo obtener las dos entidades diferentes para compartir el mismo contexto? ¿Realmente tengo que crear un nuevo contexto, cargar las dos entidades nuevamente (aunque ya las tenga) simplemente para asociarlas y guardarlas?
Si simplemente me perdí una pregunta / respuesta apropiada, por favor, dirígeme al lugar correcto.
internal class Program {
private static void Main(string[] args) {
DeleteAllEntities();
CreateInitialEntities();
Owner o = LoadOwner();
Child c = LoadChild();
AssociateAndSave(o, c);
}
private static void AssociateAndSave(Owner o, Child c) {
using (var context = new ModelEntities()) {
// Exception occurs on the following line.
o.Children.Add(c);
context.Attach(o);
context.SaveChanges();
}
}
private static Owner LoadOwner() {
using (var context = new ModelEntities()) {
return ((from o in context.Owners
select o).First());
}
}
private static Child LoadChild() {
using (var context = new ModelEntities()) {
return ((from c in context.Children
select c).First());
}
}
private static void CreateInitialEntities() {
using (var context = new ModelEntities()) {
Owner owner = new Owner();
Child child = new Child();
context.Owners.AddObject(owner);
context.Children.AddObject(child);
context.SaveChanges();
}
}
private static void DeleteAllEntities() {
using (var context = new ModelEntities()) {
List<Child> children = (from c in context.Children
select c).ToList();
foreach (var c in children)
context.Children.DeleteObject(c);
List<Owner> owners = (from o in context.Owners
select o).ToList();
foreach (var o in owners)
context.Owners.DeleteObject(o);
context.SaveChanges();
}
}
}
Debería obtener una referencia a los objetos hijo y propietario en el mismo contexto. Un enfoque para esto sería obtener los identificadores y luego pasarlos como parámetros al método AssociateAndSave(int oId, int cId)
.
Luego, recupera las referencias a los objetos en el mismo contexto y crea el archivo adjunto.
private static void Main(string[] args)
{
DeleteAllEntities();
CreateInitialEntities();
int oId = LoadOwnerId();
int cId = LoadChildId();
AssociateAndSave(oId, cId);
}
private static int LoadOwnerId()
{
using (var context = new ModelEntities())
{
return (from o in context.Owners
select o).First().Id;
}
}
private static int LoadChildId()
{
using (var context = new ModelEntities())
{
return (from c in context.Children
select c).First().Id;
}
}
private static void AssociateAndSave(int oId, int cId)
{
using (var context = new ModelEntities())
{
var owner = (from o in context.Owners
select o).FirstOrDefault(o => o.ID == oId);
var child = (from o in context.Children
select o).FirstOrDefault(c => c.ID == cId);
owner.Children.Add(child);
context.Attach(owner);
context.SaveChanges();
}
}
No puede eliminar objetos de un contexto, con una instancia de otro contexto, porque cada contexto rastrea sus objetos por separado.
Una idea sería proporcionar a cada uno de sus métodos un parámetro de su tipo de contexto para que sus operaciones se realicen dentro del mismo contexto.
EX:
private static void CrudOperationExample(DBContext contextInstane)
{
//perform crud operations.
}
Si quieres hacerlo más agradablemente, te sugiero que busques la inyección de dependencia, ya que es muy útil en ORM.