比如有两个实体,Class班级,Student学生。一个班级有多个学生。
场景:
查出某个班级的所有学生(同时包含班级信息) -> 然后修改学生信息 -> 修改实体状态 -> 提交数据库
重点在于我使用AsNoTracking()不跟踪查询结果的实体状态,以及Include()预加载学生班级实体。这样的结果就使得查出来的List<Student>脱离上下文的状态管理,同时每一个实体都包含同一个班级对象。
关系图:
查询代码:
List<Student2> studens;
using (MyDbContext db = new MyDbContext())
{
studens = db.Student2
.AsNoTracking() //重点
.Include("MyClass") //重点
.Where(r => r.ClassId == 1).ToList(); //具体是哪个班级不重要,这里只是测试,班级也可能是不固定的
}
修改Student数据:
studens[0].StuName = "新名字1";
studens[1].StuName = "新名字2";
修改实体状态,提交数据库:
using (MyDbContext db = new MyDbContext())
{
foreach (var i in studens)
{
var entry = db.Entry(i); //问题就出在Loop循环第二次
entry.State = System.Data.Entity.EntityState.Unchanged;
entry.Property(r => r.StuName).IsModified = true;
}
db.SaveChanges();
}
ERROR:Attaching an entity of type 'Entity.TableClass' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
原因就是所有的实体都是非跟踪的,所有的Student List引用的班级对象是同一个,主键ID是一样的,所以在第二次var entry = db.Entry(i);的时候就冲突了。
目前能想到的办法是 1.手动将所有MyClass导航属性置为null,然后提交数据库。缺点是很麻烦。
不知道有没有好的解决方案