c# - one - entity framework relationships
objeto de entidad no puede ser referenciado por varias instancias de IEntityChangeTracker. al agregar objetos relacionados a la entidad en Entity Framework 4.1 (9)
Alternativamente a la inyección y aún peor Singleton, puede llamar al método Detach antes de Agregar.
EntityFramework 6: ((IObjectContextAdapter)cs).ObjectContext.Detach(city1);
EntityFramework 4: cs.Detach(city1);
Hay otra manera, en caso de que no necesite el primer objeto DBContext. Simplemente envuélvelo con la palabra clave:
Payroll.Entities.City city1;
using (CityService cs = new CityService())
{
city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value));
}
Estoy tratando de guardar los detalles del empleado, que tiene referencias con City. Pero cada vez que trato de guardar mi contacto, que está validado, obtengo la excepción "ADO.Net Entity Framework. Un objeto de entidad no puede ser referenciado por múltiples instancias de IEntityChangeTracker"
Había leído tantas publicaciones pero aún no obtenía la idea exacta de qué hacer ... mi código de clic para guardar está a continuación.
protected void Button1_Click(object sender, EventArgs e)
{
EmployeeService es = new EmployeeService();
CityService cs = new CityService();
DateTime dt = new DateTime(2008, 12, 12);
Payroll.Entities.Employee e1 = new Payroll.Entities.Employee();
Payroll.Entities.City city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value));
e1.Name = "Archana";
e1.Title = "aaaa";
e1.BirthDate = dt;
e1.Gender = "F";
e1.HireDate = dt;
e1.MaritalStatus = "M";
e1.City = city1;
es.AddEmpoyee(e1,city1);
}
y el código de servicio del empleado
public string AddEmpoyee(Payroll.Entities.Employee e1, Payroll.Entities.City c1)
{
Payroll_DAO1 payrollDAO = new Payroll_DAO1();
payrollDAO.AddToEmployee(e1); //Here I am getting Error..
payrollDAO.SaveChanges();
return "SUCCESS";
}
En mi caso, estaba usando el Marco de Identidad ASP.NET. UserManager.FindByNameAsync
método integrado UserManager.FindByNameAsync
para recuperar una entidad ApplicationUser
. Luego intenté hacer referencia a esta entidad en una entidad recién creada en un DbContext
diferente. Esto resultó en la excepción que originalmente viste.
Lo resolví creando una nueva entidad ApplicationUser
con solo el Id
del método UserManager
y haciendo referencia a esa nueva entidad.
Este es un hilo antiguo, pero otra solución, que prefiero, es simplemente actualizar cityId y no asignar el modelo de agujero City a Employee ... para que el empleado se vea así:
public class Employee{
...
public int? CityId; //The ? is for allow City nullable
public virtual City City;
}
Entonces es suficiente asignar:
e1.CityId=city1.ID;
Fuente de error:
ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.Name);
ApplicationDbContext db = new ApplicationDbContent();
db.Users.Uploads.Add(new MyUpload{FileName="newfile.png"});
await db.SavechangesAsync();/ZZZZZZZ
Espero que alguien ahorre un tiempo precioso
Los pasos para reproducir se pueden simplificar a esto:
var contextOne = new EntityContext();
var contextTwo = new EntityContext();
var user = contexOne.Users.FirstOrDefault();
var group = new Group();
group.User = user;
contextTwo.Groups.Add(group);
contextTwo.SaveChanges();
Código sin error:
var context = new EntityContext();
var user = context.Users.FirstOrDefault();
var group = new Group();
group.User = user; // Be careful when you set entity properties.
// Be sure that all objects came from the same context
context.Groups.Add(group);
context.SaveChanges();
Porque estas dos líneas ...
EmployeeService es = new EmployeeService();
CityService cs = new CityService();
... no tome un parámetro en el constructor, supongo que crea un contexto dentro de las clases. Cuando cargas la city1
...
Payroll.Entities.City city1 = cs.SelectCity(...);
... adjunta la city1
al contexto en CityService
. Más tarde, agrega una city1
como referencia al nuevo Employee
e1
y agrega e1
incluida esta referencia a city1
al contexto en EmployeeService
. Como resultado, tiene city1
adjuntado a dos contextos diferentes, de lo que se queja la excepción.
Puede solucionar esto creando un contexto fuera de las clases de servicio e inyectándolo y utilizándolo en ambos servicios:
EmployeeService es = new EmployeeService(context);
CityService cs = new CityService(context); // same context instance
Sus clases de servicio se parecen un poco a los repositorios que son responsables de un solo tipo de entidad. En tal caso, siempre tendrá problemas tan pronto como las relaciones entre entidades estén involucradas cuando use contextos separados para los servicios.
También puede crear un único servicio que sea responsable de un conjunto de entidades estrechamente relacionadas, como EmployeeCityService
(que tiene un único contexto) y delegue toda la operación en su método Button1_Click
a un método de este servicio.
Tuve el mismo problema pero mi problema con la solución de @Sumauma (aunque excelente en ciertos casos) es que recomienda pasar el contexto al servicio, lo que implica que el contexto está disponible desde mi controlador. También fuerza un fuerte acoplamiento entre mi controlador y las capas de servicio.
Estoy usando Dependency Injection para inyectar las capas de servicio / repositorio en el controlador y, como tal, no tengo acceso al contexto desde el controlador.
Mi solución fue hacer que las capas de servicio / repositorio usaran la misma instancia del contexto: Singleton.
Contexto Singleton Class:
Referencia: http://msdn.microsoft.com/en-us/library/ff650316.aspx
y http://csharpindepth.com/Articles/General/Singleton.aspx
public sealed class MyModelDbContextSingleton
{
private static readonly MyModelDbContext instance = new MyModelDbContext();
static MyModelDbContextSingleton() { }
private MyModelDbContextSingleton() { }
public static MyModelDbContext Instance
{
get
{
return instance;
}
}
}
Clase de repositorio:
public class ProjectRepository : IProjectRepository
{
MyModelDbContext context = MyModelDbContextSingleton.Instance;
Existen otras soluciones, como instanciar el contexto una vez y pasarlo a los constructores de las capas de servicio / repositorio u otro sobre el cual estoy implementando el patrón Unidad de trabajo. Estoy seguro de que hay más ...
Tuve el mismo problema y pude resolver la creación de una nueva instancia del objeto que intentaba actualizar. Luego pasé ese objeto a mi repositorio.
Use el mismo objeto DBContext a lo largo de la transacción.