Smi*_*ily 161 c# asp.net ado.net entity-framework foreign-keys
我正在尝试保存员工详细信息,其中包含对City的引用.但每当我尝试保存我的联系人时,我都会得到例外"ADO.Net实体框架实例对象不能被IEntityChangeTracker的多个实例引用"
我读了这么多帖子,但仍然没有弄清楚该怎么做...我的保存按钮点击代码如下
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);
}
Run Code Online (Sandbox Code Playgroud)
和Employeeservice代码
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";
}
Run Code Online (Sandbox Code Playgroud)
Sla*_*uma 235
因为这两条线......
EmployeeService es = new EmployeeService();
CityService cs = new CityService();
Run Code Online (Sandbox Code Playgroud)
...不要在构造函数中使用参数,我猜你在类中创建了一个上下文.当你加载city1...
Payroll.Entities.City city1 = cs.SelectCity(...);
Run Code Online (Sandbox Code Playgroud)
...你附上city1了上下文CityService.稍后您添加一个city1作为对new的引用Employee e1并添加,e1 包括对该city1上下文的引用EmployeeService.结果你city1附加了两个不同的上下文,这是异常所抱怨的.
您可以通过在服务类之外创建上下文并在两个服务中注入和使用它来解决此问题:
EmployeeService es = new EmployeeService(context);
CityService cs = new CityService(context); // same context instance
Run Code Online (Sandbox Code Playgroud)
您的服务类看起来有点像只负责单个实体类型的存储库.在这种情况下,当您为服务使用单独的上下文时,一旦涉及实体之间的关系,您将始终遇到麻烦.
您还可以创建一个服务,该服务负责一组密切相关的实体,例如EmployeeCityService(具有单个上下文)并将Button1_Click方法中的整个操作委托给此服务的方法.
Pav*_*nik 29
重现的步骤可以简化为:
var contextOne = new EntityContext();
var contextTwo = new EntityContext();
var user = contextOne.Users.FirstOrDefault();
var group = new Group();
group.User = user;
contextTwo.Groups.Add(group);
contextTwo.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
代码没有错误:
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();
Run Code Online (Sandbox Code Playgroud)
小智 9
这是一个旧线程,但另一个解决方案,我更喜欢,只是更新cityId而不是将孔模型City分配给Employee ...要做到这一点,Employee应该如下所示:
public class Employee{
...
public int? CityId; //The ? is for allow City nullable
public virtual City City;
}
Run Code Online (Sandbox Code Playgroud)
然后它足够分配:
e1.CityId=city1.ID;
Run Code Online (Sandbox Code Playgroud)
小智 5
我有同样的问题,但我对@ Slauma的解决方案的问题(虽然在某些情况下很好)是它建议我将上下文传递给服务,这意味着上下文可以从我的控制器获得.它还强制我的控制器和服务层之间紧密耦合.
我正在使用依赖注入将服务/存储库层注入控制器,因此无法从控制器访问上下文.
我的解决方案是让服务/存储库层使用相同的上下文实例 - 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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
存储库类:
public class ProjectRepository : IProjectRepository
{
MyModelDbContext context = MyModelDbContextSingleton.Instance;
[...]
Run Code Online (Sandbox Code Playgroud)
确实存在其他解决方案,例如实例化上下文一次并将其传递到服务/存储库层的构造函数或另一个我读到的实现工作单元模式的解决方案.我相信还有更多......
除了注入和更糟糕的单例之外,您可以在 Add 之前调用Detach方法。
实体框架 6: ((IObjectContextAdapter)cs).ObjectContext.Detach(city1);
实体框架 4: cs.Detach(city1);
还有另一种方法,以防您不需要第一个 DBContext 对象。只需使用关键字包装它:
Payroll.Entities.City city1;
using (CityService cs = new CityService())
{
city1 = cs.SelectCity(Convert.ToInt64(cmbCity.SelectedItem.Value));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
168209 次 |
| 最近记录: |