2016-03-11 93 views
0

我想執行更新到對象,但它總是會引發異常illegally attempted to associate a proxy with two open session。我可以插入,但更新我不能。如何在NHibernate中執行更新?

我該如何解決?

DBCONNECT

public class DBConnect { 

      private static ISessionFactory session; 
      private const String HOST = "localhost"; 
      private const String USER = "root"; 
      private const String PASSWORD = ""; 
      private const String DB = "pubcontrol"; 

      /** create a connection with database */ 
      private static ISessionFactory createConnection() { 

       if (session != null) 
        return session; 

       //database configs 
       FluentConfiguration _config = Fluently.Configure().Database(MySQLConfiguration.Standard.ConnectionString(
                      x => x.Server(HOST). 
                       Username(USER). 
                       Password(PASSWORD). 
                       Database(DB) 
                      )) 
                      .Mappings(m => m.FluentMappings.AddFromAssemblyOf<PerfilMap>()) 
                      .Mappings(m => m.FluentMappings.AddFromAssemblyOf<ModuloMap>()) 
                      .Mappings(m => m.FluentMappings.AddFromAssemblyOf<PermissaoMap>()) 
                      .ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(false, true)); 

       session = _config.BuildSessionFactory(); 
       return session; 
      } 


      /** open a session to make transactions */ 
      public static ISession openSession() { 
       return createConnection().OpenSession(); 
      } 
     } 

GenericDAO

public class GenericDAO<T> : IPersist<T> where T : class { 

     public void insert(T obj) { 
      ISession _session = DBConnect.openSession(); 
      ITransaction _transaction = _session.BeginTransaction(); 
      try { 
       _session.Save(obj); 
       _transaction.Commit(); 
      }catch (Exception e) { 
       if (!_transaction.WasCommitted) { 
        _transaction.Rollback(); 
       } 
       MessageBox.Show("Erro tentando salvar: " + e.Message, "Aviso", 
       MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
     } 


     public void update(T obj) { 
      ISession _session = DBConnect.openSession(); 
      ITransaction _transaction = _session.BeginTransaction(); 
      try { 
       _session.Update(obj); 
       _transaction.Commit(); 
      }catch (Exception e) { 
       if (!_transaction.WasCommitted) { 
        _transaction.Rollback(); 
       } 
       MessageBox.Show("Erro tentando alterar: " + e.Message, "Aviso", 
       MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
     } 



     public void delete(T obj) { 
      ISession _session = DBConnect.openSession(); 
      ITransaction _transaction = _session.BeginTransaction(); 
      try { 
       _session.Delete(obj); 
       _transaction.Commit(); 
      }catch (Exception e) { 
       if (!_transaction.WasCommitted) { 
        _transaction.Rollback(); 
       } 
       MessageBox.Show("Erro tentando deletar: " + e.Message, "Aviso", 
       MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
     } 



     public T findObject(long id) { 
      ISession _session = DBConnect.openSession(); 
      return _session.Load<T>(id); 
     } 


     public void saveOrUpdate(T obj) { 
      ISession _session = DBConnect.openSession(); 
      ITransaction _transaction = _session.BeginTransaction(); 
      try { 
       _session.SaveOrUpdate(obj); 
       _transaction.Commit(); 
      }catch (Exception e) { 
       if (!_transaction.WasCommitted) { 
        _transaction.Rollback(); 
       } 
       MessageBox.Show("Erro tentando salvar ou alterar: " + e.Message, "Aviso", 
       MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
     } 
    } 

PermissaoDAO

public class PermissaoDAO : GenericDAO<Permissao> { 

     public IList<Permissao> findAll() { 
      ISession _session = DBConnect.openSession(); 
      IList<Permissao> list = _session.CreateQuery("FROM Permissao p")     
       .List<Permissao>(); 
      return list; 
     } 


     /** verifica se o perfil ou o modulo estao adicionados */ 
     public Boolean isExistPerfilAndModulo(Permissao permissao) { 
      ISession _session = DBConnect.openSession(); 
      IList<Permissao> list = _session.CreateQuery("FROM Permissao p WHERE p.perfil = :p AND p.modulo = :m") 
       .SetParameter("p", permissao.perfil) 
       .SetParameter("m", permissao.modulo) 
       .List<Permissao>(); 
      if (list.Count > 0) { 
       return true; 
      } 
      return false; 
     } 

     /** retorna a permissao */ 
     public Permissao getPermissao(Permissao permissao) { 
      ISession _session = DBConnect.openSession(); 
      IList<Permissao> list = _session.CreateQuery("FROM Permissao p WHERE p.perfil = :p AND p.modulo = :m").SetMaxResults(1) 
       .SetParameter("p", permissao.perfil) 
       .SetParameter("m", permissao.modulo) 
       .List<Permissao>(); 
      return list[0]; 
     } 


    } 

製作更新

/** insere Perfil + Modulo */ 
     private void insertPerfilModulo() { 
      PermissaoDAO dao = new PermissaoDAO(); 
      Perfil perfil = (Perfil)cbxPerfilModulo.SelectedItem; 
      IList<Modulo> lista = getListaModulo(); 

      foreach(Modulo m in lista){     
       Permissao permissao = new Permissao(); 
       permissao.perfil = perfil; 
       permissao.modulo = m; 

       Boolean exist = dao.isExistPerfilAndModulo(permissao);     
       if (exist) { 
        Permissao p = dao.getPermissao(permissao); 
        dao.update(p); 
       }else { 
        dao.insert(permissao); 
       } 
      } 
     } 
+1

有一個非常糟糕的交易處理並設計誤解。交易應該跨越整個業務運營,否則他們沒有任何意義。要使用延遲加載,會話必須在讀取屬性時可用。考慮到所有這些,會話和事務不能爲每個查詢打開。此代碼不屬於「DAO」。無論如何,你在哪裏關閉會議?順便說一句:更新是由NHibernate隱式完成的,你不需要調用任何東西。這隻有在按照打算使用NH的方式使用時纔有效。 –

+0

更好地避免生成寬水平卷軸的代碼塊。嘗試重新格式化它們。就個人而言,它可能會導致我跳過這個問題。 –

回答

1

您不應該對同一對象使用多個會話。您不應該爲每個數據庫操作創建一個事務,這樣交易就沒有任何意義。讓每個會話和事務處理跨越整個業務操作,並且不要忘記最後關閉(或處置)兩者。

更新對於會話中的每個對象都是隱含的。每個查詢或插入的對象都由會話管理。

當使用NHibernate,代碼通常看起來像這樣(示範,可以看看這取決於你如何設計你的DAO很大的不同,但這個概念應該是相同的):

using (session = dao.CreateSession()) 
using (session.CreateTransaction()) 
{ 
    var myObject = dao.Get<MyObject>(id); 
    if (myObject == null) 
    { 
    myObject = new MyObject(); 
    dao.Insert(myObject); 
    } 
    myObject.Property = 3; 
    dao.Commit(); 
} 
+0

你看了我的代碼嗎?你在GenericDAO或PermissaoDAO中改變了什麼? – FernandoPaiva

+1

@FernandoPaiva看起來您需要了解應該如何使用ORM。 (你目前的代碼漏洞並不是特定於NHibernate的)。對於MVC應用程序,這個[博客系列](/ a/5908834/1178314)是一個起點。 –