我有一个使用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 !!!
答案 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关系中的关联。你几乎没有(可能永远不需要)明确地操纵关系状态。如果你觉得有必要这样做,很可能表明你忽略了一种更容易达到你想要的方式。