0

私のリポジトリ更新メソッドでは、最初に更新されたエンティティのコレクションに追加する必要がある既存のオブジェクトをアタッチします。これにより、エンティティを別の既存のエンティティに関連付け、新しいエンティティを作成しないことを 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ます。

4

1 に答える 1

0

私は少し前にこの問題を抱えていました。基本的には、コンテキスト内でエンティティがメモリにロードされ、それを同じコンテキストにアタッチしようとしていることをコンパイラが伝えていました (2 回目の forloop 反復 -アタッチされているオブジェクトはその初期コンテキストにあります)。

この問題を解決するには、.Add メソッドに対して別のコンテキスト (新しい "using" 呼び出し) を使用すると、これが機能します。それが私が見つけた唯一の回避策です。

つまり (私の UnitOfWork = 通常のコンテキスト)

UnitOfWork _context = new UnitOfWork();

// Add 1
_context.Add(obj);

using(UnitOfWork context = new UnitOfWork()){
   // Do second addition routines here based on objects used in add 1.
   context.Add(childobj);
   context.SaveChanges();
}

_context.SaveChanges();
于 2013-02-19T12:06:10.410 に答える