在EF5中更新多对多关系时出错

时间:2012-12-04 05:10:51

标签: entity-framework

我有一个使用Entity Framework 5的N-Layers的ASP.NET WebForms项目。 我有两个实体:Cliente和Banda。 一个Cliente可能有很多Banda,而一个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方法时,运行成功,但第二次出现此错误:

“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();
            }
        }

谢谢Gert Arnold !!!

1 个答案:

答案 0 :(得分: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);中是否有这个中断代码,因为(显然)我不知道那里发生了什么。

如您所见,您可以通过添加/删除对象来添加和删除m:m关系中的关联。你几乎没有(可能永远不需要)明确地操纵关系状态。如果你觉得有必要这样做,很可能表明你忽略了一种更容易达到你想要的方式。