4

Entity Framework 5 を使用した N レイヤーを使用した ASP.NET WebForms プロジェクトがあります。Cliente と Banda の 2 つのエンティティがあります。1 つの Cliente に多くの Banda があり、1 つの Banda に複数の Cliente がある場合があります。

bussines レイヤーには、次のコードがあります。

public void Update(Cliente cliente)
    {
        using (MegaStudioEntities contexto = new MegaStudioEntities())
        {
            if (contexto.Entry(cliente).State == EntityState.Detached)
                contexto.Entry(cliente).State = EntityState.Modified;

            //Delete existing relations
            var qBandas = from qb in contexto.Bandas.Where(b => b.Clientes.Any(c => c.IdCliente == cliente.IdCliente))
                          select qb;


            foreach (Banda b in qBandas.ToList())
                ((IObjectContextAdapter)contexto).ObjectContext.ObjectStateManager.ChangeRelationshipState(cliente, b, c => c.Bandas, EntityState.Deleted);

            contexto.SaveChanges();

            //Adding new relations
            foreach (Banda banda in cliente.Bandas)
            {
                contexto.Bandas.Attach(banda);
                ((IObjectContextAdapter)contexto).ObjectContext.ObjectStateManager.ChangeRelationshipState(cliente, banda, c => c.Bandas, EntityState.Added);
            }

            cliente.TipoCliente = contexto.TipoClientes.Find(cliente.IdTipoCliente);
            cliente.FechaModificacion = System.DateTime.Now;
            Encriptar(cliente);
            contexto.SaveChanges();
        }
    }

初めて Update メソッドを呼び出したときは正常に実行されましたが、2 回目には次のエラーが発生しました。

「同じキーを持つオブジェクトが既に ObjectStateManager に存在します。ObjectStateManager は、同じキーを持つ複数のオブジェクトを追跡できません。」

何を閉じるのを忘れていますか?これは、EF5 で多対多の関係を更新する正しい方法ですか?

前もって感謝します!!!

マーティン

更新 1:

最後に、私のコードは次のようになります。

public void Update(Cliente cliente)
        {
            using (MegaStudioEntities contexto = new MegaStudioEntities())
            {
                Cliente savedClient = contexto.Clientes.Find(cliente.IdCliente);

                foreach (var banda in savedClient.Bandas.ToList())
                {
                    savedClient.Bandas.Remove(contexto.Bandas.Find(banda.IdBanda));
                }

                foreach (var banda in cliente.Bandas)
                {
                    savedClient.Bandas.Add(contexto.Bandas.Find(banda.IdBanda));
                }

                contexto.Entry(savedClient).CurrentValues.SetValues(cliente);
                contexto.SaveChanges();
            }
        }

ありがとうゲルト・アーノルド!!!

4

1 に答える 1

4

オブジェクトをコンテキストにアタッチする必要はありません。したがって、そうしないことでこの例外を防ぐことができます。

public void Update(Cliente cliente)
{
    using (MegaStudioEntities contexto = new MegaStudioEntities())
    {
        Cliente savedClient = contexto.TipoClientes.Find(cliente.IdCliente);

        foreach (var banda in savedClient.Bandas.ToList())
        {
            savedClient.Bandas.Remove(banda);
        }
        foreach (var banda in cliente.Bandas)
        {
            savedClient.Bandas.Add(banda);
        }

        savedClient.IdTipoCliente = cliente.IdTipoCliente;
        savedClient.FechaModificacion = System.DateTime.Now;

        Encriptar(cliente);
        contexto.SaveChanges();
    }
}

Encriptar(cliente);(明らかに)そこで何が起こるかわからないため、このコードが壊れているかどうかはわかりません。

ご覧のとおり、オブジェクトを追加/削除することで、am:m 関係の関連付けを追加および削除します。リレーションシップの状態を明示的に操作する必要はほとんどありません (おそらくまったくありません)。それをする必要があると感じた場合、それはおそらく、あなたが望むことを達成するためのより簡単な方法を見落としていることを示しています.

于 2012-12-04T11:57:46.750 に答える