私のリポジトリ更新メソッドでは、最初に更新されたエンティティのコレクションに追加する必要がある既存のオブジェクトをアタッチします。これにより、エンティティを別の既存のエンティティに関連付け、新しいエンティティを作成しないことを 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
、同じエンティティをオブジェクト コンテキストに 2 回アタッチしようとしている可能性があることです。この場合はbasicGroup
. そのため、オブジェクトが既にアタッチされているかどうかをテストして、アタッチされていない場合にのみアタッチできると考えました。
testEntry 行を見てください。そこで、group
エンティティのEntry
ステータスを取得しようとします。私は確かにDbEntityEntry
インスタンスを取得しますが、それは常に(すべてのループ反復で)あると言っていEntityState
ますDetached
。ここで、コードを実行すると、foreach ループの最初の反復では問題ありませんが、2 回目の反復で例外が発生します。
同じキーを持つオブジェクトが ObjectStateManager に既に存在します。ObjectStateManager は、同じキーを持つ複数のオブジェクトを追跡できません。
これはわかりません。オブジェクトが ObjectStateManager に既に存在する場合、なぜDbEntityEntry
その状態が であると言うのDetached
ですか? 確かに、その状態が であることを覚えておく必要がありUnchanged
ます。