在我的存储库更新方法中,我首先附加现有对象,这些对象可能需要在执行任何其他操作之前添加到更新实体的集合中,以便 EF 意识到我想将该实体与另一个现有实体相关联,而不是创建一个新实体。所以在这个例子中,我正在使用用户组:
UserGroup basicGroup = repoGroup.GetGroupByName("BasicGroup");
List<UserGroup> updatedGroups = new List<UserGroup> { basicGroup };
foreach (var user in usersToUpdate) {
repoUser.UpdateUser(user.userId, updatedGroups);
}
[...]
public bool UpdateUser(int updatedUserId, List<UserGroup> updatedGroups) {
using (var context = new MyDbContext()) {
if (updatedGroups != null) {
// Attach groups to context before add so that EF creates a new
// relationship between entity and new items in groups collection,
// instead of creating a new entity for each new item.
foreach (UserGroup group in updatedGroups) {
var testEntry = context.Entry(group);
context.UserGroups.Attach(group);
}
}
var userToUpdate = context.Users.First(usr => usr.id == updatedUserId);
userToUpdate.UserGroups.Clear();
foreach (var group in updatedGroups) {
userToUpdate.UserGroups.Add(group);
}
context.SaveChanges();
return true;
}
}
因此,我的代码在几个用户之间循环,并尝试将一组新的组与他们关联起来。我意识到我在这里犯的错误是我.Attach
可能试图将同一个实体两次附加到对象上下文 - 在这种情况下,basicGroup
. 所以我想我可以测试一下对象是否已经被附加,如果没有附加它。
所以看看 testEntry 行。在那里,我尝试获取group
实体的Entry
状态。我确实得到了一个DbEntityEntry
实例,但它总是说EntityState
是Detached
(在每个循环迭代中)。现在,当我运行我的代码时,在 foreach 循环的第一次迭代中没问题,但在第二次迭代中,我得到了异常:
ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。
我不明白这一点;如果对象已经存在于 ObjectStateManager 中,为什么我DbEntityEntry
说它的状态是Detached
?它当然应该记住它的状态是Unchanged
。