实体对象不能被IEntityChangeTracker的多个实例引用。 同时在entity framework4.1中添加相关对象到实体

我正在尝试保存员工详细信息,该信息与城市有关。 但每次我尝试保存我的联系人,这是validation我得到exception“ADO.Netentity framework一个实体对象不能被多个IEntityChangeTracker实例引用”

我读过这么多的post,但仍然没有得到确切的想法做什么…我保存button点击代码如下

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

员工服务代码

 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"; } 

因为这两条线

 EmployeeService es = new EmployeeService(); CityService cs = new CityService(); 

…不要在构造函数中使用参数,我想你会在类中创build一个上下文。 当你加载city1

 Payroll.Entities.City city1 = cs.SelectCity(...); 

…将city1附加到city1中的上下文。 稍后,将city1添加为新Employee e1的引用,并将包括对city1此引用的 e1添加city1中的上下文中。 结果你有city1附加到两个不同的上下文,这是exception抱怨。

您可以通过在服务类之外创build一个上下文来解决这个问题,并在两个服务中注入和使用它:

 EmployeeService es = new EmployeeService(context); CityService cs = new CityService(context); // same context instance 

你的服务类看起来有点像只负责一个实体types的仓库。 在这种情况下,如果在为服务使用单独的上下文时,只要涉及到实体之间的关系,就总是会遇到麻烦。

您还可以创build一个服务,负责一组紧密相关的实体,如EmployeeCityService (具有单个上下文),并将Button1_Click方法中的整个操作委托给此服务的一个方法。

重现步骤可以简化为:

 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(); 

代码没有错误:

 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(); 

我有同样的问题,但我的问题与@ Slauma的解决scheme(虽然在某些情况下很好)是,它build议我将上下文传递到服务,这意味着上下文可从我的控制器。 它也强制我的控制器和服务层之间的紧密耦合。

我使用dependency injection来将服务/存储库层注入到控制器中,因此无法访问控制器的上下文。

我的解决scheme是让服务/存储库层使用相同的上下文实例 – 单例。

上下文Singleton类:

参考: http : //msdn.microsoft.com/en-us/library/ff650316.aspx
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; } } } 

存储库类:

 public class ProjectRepository : IProjectRepository { MyModelDbContext context = MyModelDbContextSingleton.Instance; 

其他解决scheme确实存在,例如一次实例化上下文,并将其传递到服务/存储库层的构造函数中,或者另一种解决scheme是读取有关实现“工作单元”模式的信息。 我相信还有更多…

另外注射,甚至更糟糕的单身人士,你可以调用分离方法之前添加。

EntityFramework 6 : ((IObjectContextAdapter)cs).ObjectContext.Detach(city1);

EntityFramework 4: cs.Detach(city1);

还有另一种方法,如果你不需要第一个DBContext对象。 只需使用关键字包装它:

 Payroll.Entities.City city1; using (CityService cs = new CityService()) { city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value)); } 

这是一个古老的线程,但我更喜欢的另一个解决scheme是更新cityId,而不是将空洞模型City分配给Employee …要这样做Employee应该看起来像:

 public class Employee{ ... public int? CityId; //The ? is for allow City nullable public virtual City City; } 

那么分配就足够了:

 e1.CityId=city1.ID; 

在我的情况下,我正在使用ASP.NET身份框架。 我曾经使用内置的UserManager.FindByNameAsync方法来检索一个ApplicationUser实体。 然后我尝试在不同的DbContext上新创build的实体上引用此实体。 这导致你原来看到的例外。

我通过创build一个新的ApplicationUser实体来解决这个问题,只需要使用UserManager方法中的Id并引用新的实体。

我有同样的问题,我可以解决我想要更新的对象的新实例。 然后我把这个东西传给了我的回报。

在整个事务中使用相同的DBContext对象。

错误来源:

 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 

希望有人节省一些宝贵的时间