当我收到相同的表格行两次以便在相同的上下文中进行更新时,我得到:
“ AcceptChanges无法继续,因为对象的键值与ObjectStateManager中的另一个对象冲突。确保在调用AcceptChanges之前键值是唯一的。”
问题发生在ChangeState方法上。
我所拥有的内容可以简化为:
var obj1 = new test() { id = 1,name = "oiu"};
var dc = Context.Create();
dc.test.AddObject(obj1);
if (dc.test.Any(a => a.id == obj1.id))
dc.ObjectStateManager.GetObjectStateEntry(obj1).ChangeState(EntityState.Modified);
dc.SaveChanges();
//---- another iteration of the reading thread, another object, but same context:
var obj2 = new test() { id = 1, name = "ois" };
dc.test.AddObject(obj2);
if (dc.test.Any(a => a.id == obj2.id))
dc.ObjectStateManager.GetObjectStateEntry(obj2).ChangeState(EntityState.Modified);
dc.SaveChanges();
有出路吗?
答案 0 :(得分:1)
那么,你想做什么?您告诉EF和数据库(我假设)“id”是对象/行的唯一标识符。然后,你已经告诉它你要添加两个具有相同唯一id(“1”)的对象,并希望它能够处理工作。
是否要添加具有相同唯一ID的对象,或者是否要添加一个,然后更新现有行/对象以将名称属性从“oiu”更改为“ois”。如果是前者,请不要将“id”变成pkid。如果是后者,请不要告诉EF你想要两次添加对象。添加一次,更新现有对象。
答案 1 :(得分:0)
您只能将对象连接到上下文一次(通过从数据库加载对象或调用Attach
或AddObject
)。将对象连接到上下文后,您有责任对所有修改使用相同的实例。上下文使用标识映射模式 - 它意味着它通过其唯一标识(基于主键和实体集的实体键)跟踪对象,并且仅允许具有给定实体键的类型的一个实例。唯一的例外是在保存更改之前添加EntityKey
为临时的新对象,但如果将状态更改为Modified
则不是这样。
如果您在测试的其余部分中不知道该实例,则可以查询ObjectStateManager.GetObjectStateEntries
并搜索您的实例(每个条目都具有引用该实例的Entity
属性。)