使用EF对建立了关系的表新增记录时出现:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker 或一个实体对象不能由多个 IEntityChangeTracker 实例引用
在学习MVC+EF做demo时碰到的一个异常信息。在网上查了些,看得不是很明白,就自己折腾了一会儿。
先上出错的代码:
public class CollegeInfo
{
private StudentManageContext stuCtx=new StudentManageContext();
public Models.CollegeInfoModel GetModel(Guid collegeId)
{
var model = stuCtx.CollegeInfoes.SingleOrDefault(s => s.CollegeId == collegeId); return model;
} public int Add(Models.CollegeInfoModel model)
{
stuCtx.CollegeInfoes.Add(model);
int count = stuCtx.SaveChanges();
return count;
} public int Update(Models.CollegeInfoModel model)
{
Models.CollegeInfoModel oldModel = stuCtx.CollegeInfoes.Find(model.CollegeId);
oldModel = model;
stuCtx.Entry(oldModel).State = System.Data.EntityState.Modified;
return stuCtx.SaveChanges();
}
}
<!–
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
–>
public class DepartmentInfo
{
private StudentManageContext stuCtx=new StudentManageContext();
public Models.DepartmentInfoModel GetModel(Guid departmentId)
{
var model = stuCtx.DepartmentInfoes.SingleOrDefault(s => s.DepartmentId == departmentId); return model;
} public int Add(Models.DepartmentInfoModel model)
{
stuCtx.DepartmentInfoes.Add(model);
int count = stuCtx.SaveChanges(); return count;
} public int Update(Models.DepartmentInfoModel model)
{
Models.DepartmentInfoModel oldModel = stuCtx.DepartmentInfoes.Find(model.DepartmentId);
oldModel = model;
stuCtx.Entry(oldModel).State = System.Data.EntityState.Modified;
return stuCtx.SaveChanges();
}
}
使用表关系图:
<!–
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
–>
两个表是一对多的关系。DepartmentInfo 中的collegeInfoId是外键。
添加DepartmentInfo代码:
static void Main(string[] args)
{
Database.SetInitializer<StudentManageContext>(new DropCreateDatabaseIfModelChanges<StudentManageContext>());
CollegeInfoModel collegex = new BLL.CollegeInfo().GetModel(new Guid(“B956CA6F-DD7D-4436-9099-484366A5F0B7”));
DepartmentInfoModel depart = new DepartmentInfoModel()
{
DepartmentId = Guid.NewGuid(),
DepartmentName = "depart" + DateTime.Now.ToString(),
CollegeInfoObj = collegex
};
new BLL.DepartmentInfo().Add(depart);
}
<!–
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
–>
这时会出现An entity object cannot be referenced by multiple instances of IEntityChangeTracker 或一个实体对象不能由多个 IEntityChangeTracker 实例引用的异常
原因是 CollegeInfoModel collegex = new BLL.CollegeInfo().GetModel(new Guid(“B956CA6F-DD7D-4436-9099-484366A5F0B7”)); 和 new BLL.DepartmentInfo().Add(depart); 这两句代码使用的是两个不同的StudentManageContext 对象造成的,可以仔细看看出错代码,两个类都有 private StudentManageContext stuCtx=new StudentManageContext(); ,到这儿你是否明白了呢。简单的来说,你要做的操作都必须在同一DbContext上完成。注:StudentManageContext派生于DbContext.
解决方案一:
static void Main(string[] args)
{
Database.SetInitializer<StudentManageContext>(new DropCreateDatabaseIfModelChanges<StudentManageContext>()); CollegeInfoModel collegex = new BLL.CollegeInfo().GetModel(new Guid("B956CA6F-DD7D-4436-9099-484366A5F0B7")); DepartmentInfoModel depart = new DepartmentInfoModel()
{
DepartmentId = Guid.NewGuid(),
DepartmentName = "depart" + DateTime.Now.ToString(), };
//new BLL.DepartmentInfo().Add(depart); 将这句代码改成下面两句
collegex.Departments.Add(depart);
new BLL.CollegeInfo().Update(collegex);
}
原因就是:Update时与GetModel用得时同一个DBContext。
解决方案二:
public class CollegeInfo:BaseModel
{
public Models.CollegeInfoModel GetModel(Guid collegeId)
{
var model = stuCtx.CollegeInfoes.SingleOrDefault(s => s.CollegeId == collegeId); return model;
} public int Add(Models.CollegeInfoModel model)
{
stuCtx.CollegeInfoes.Add(model);
int count = stuCtx.SaveChanges();
return count;
} public int Update(Models.CollegeInfoModel model)
{
Models.CollegeInfoModel oldModel = stuCtx.CollegeInfoes.Find(model.CollegeId);
oldModel = model;
stuCtx.Entry(oldModel).State = System.Data.EntityState.Modified;
return stuCtx.SaveChanges();
}
}
public class DepartmentInfo:BaseModel
{ public Models.DepartmentInfoModel GetModel(Guid departmentId)
{
var model = stuCtx.DepartmentInfoes.SingleOrDefault(s => s.DepartmentId == departmentId); return model;
} public int Add(Models.DepartmentInfoModel model)
{
stuCtx.DepartmentInfoes.Add(model);
int count = stuCtx.SaveChanges(); return count;
} public int Update(Models.DepartmentInfoModel model)
{
Models.DepartmentInfoModel oldModel = stuCtx.DepartmentInfoes.Find(model.DepartmentId);
oldModel = model;
stuCtx.Entry(oldModel).State = System.Data.EntityState.Modified;
return stuCtx.SaveChanges();
}
}
public abstract class BaseModel
{
protected StudentManageContext stuCtx = null;
public BaseModel()
{
stuCtx = DataCache.GetCache("StudentManageContext") as StudentManageContext;
if (stuCtx == null)
{
stuCtx = new StudentManageContext();
DataCache.SetCache("StudentManageContext", stuCtx);
}
}
}
这样的话可以让CollegeInfo和DepartmentInfo共用同一个DBContext。
<!–
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
–>
<!–
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
–>
<!–
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
–>