2012-12-04 66 views
4

我有一個使用實體框架5的N層的ASP.NET WebForms項目。 我有兩個實體:Cliente和Banda。 一個Cliente可能有很多班的,而且一個班可能有很多Cliente的在EF5中更新多對多關係時出錯

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

感謝格特·阿諾德!

+0

你在哪一行得到錯誤? –

+0

wery重要的行'savedClient.Bandas.Remove(contexto.Bandas.Find(banda.IdBanda))' – Kuncevic

回答

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關係中的關聯。你幾乎沒有(可能永遠)不需要明確地操縱關係狀態。如果你覺得有必要這樣做,最有可能表明你忽略了一個更簡單的方法來實現你想要的。

+0

嗨,謝謝你! 那麼其他的客戶屬性呢?我是否需要這樣做:「savedClient.Name = cliente.Name;」? – mneu

+0

僅在更改時才適用。基本上你必須複製在UI中允許更改的屬性。 –

+0

我需要從你的代碼中改變的唯一東西是在這一行:「savedClient.Bandas.Remove(contexto.Bandas.Find(banda.IdBanda));」,因爲banda沒有附加到上下文中。 感謝您的解決方案!我唯一不喜歡的是手動分配所有屬性。謝謝! – mneu