4

我有一个使用 Entity Framework 5 的 N 层的 ASP.NET WebForms 项目。我有两个实体:Cliente 和 Banda。一个客户可能有很多班达,一个班达可能有很多客户

在商务层我有这个代码:

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

谢谢格特阿诺德!!!

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 回答