【问题标题】:Error when updating many to many relation in EF5在 EF5 中更新多对多关系时出错
【发布时间】:2012-12-04 05:10:50
【问题描述】:

我有一个使用 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();
            }
        }

感谢格特·阿诺德!!!

【问题讨论】:

  • 你在哪一行得到错误?
  • 非常重要的一行savedClient.Bandas.Remove(contexto.Bandas.Find(banda.IdBanda))

标签: entity-framework


【解决方案1】:

您实际上不必将任何对象附加到上下文中。因此,您可以通过不这样做来防止此异常。

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 关系中的关联。您几乎从不(可能从不)需要明确地操纵关系状态。如果您觉得有必要这样做,这很可能表明您忽略了实现您想要的更简单的方法。

【讨论】:

  • 您好,感谢您的回答! cliente 的其余部分呢?,我必须这样做:“savedClient.Name = cliente.Name;”吗?
  • 仅当它被改变时。基本上,您必须复制允许在 UI 中更改的属性。
  • 我唯一需要从您的代码中更改的是这一行:“savedClient.Bandas.Remove(contexto.Bandas.Find(banda.IdBanda));”,因为 banda 未附加到上下文。感谢您的解决方案!,我唯一不喜欢的是手动分配所有属性。谢谢!
  • 看起来不错!你能给我举个例子吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-27
  • 2021-04-11
  • 2017-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多