2009-01-29 15 views
11

Tengo una lista de 10 objetos de datos que deseo insertar/actualizar en la base de datos usando NHibernate. Si se lanza una excepción (digamos una violación de clave primaria), quiero insertar/actualizar la otra 9. Invertí cada operación de objeto en su propia transacción atómica, y retrotrae la transacción si hay una excepción. El problema es que si una transacción causa una excepción y se revierte, en la siguiente transacción Nhibernate se queja con el error: null id en la entrada Nexus.Data.PortfolioCorporateEntity (no vacíe la sesión después de que ocurra una excepción)Nhibernate: manejo de una excepción de transacción IT para que nuevas transacciones puedan continuar con la misma ISession

Mi programa principal es simple. Crea una sesión a partir de un sessionfactory, crea la capa de acceso a los datos, hace algo de trabajo en los objetos de datos y luego intenta persistir esos objetos de datos en la base de datos.

sessionsManager = new NHibernateSessionManager(); 
     session = sessionsManager.GetSession(); 
     DALC = new NHibernateDataProvider(session); 

     … 

     foreach (var pce in pces) 
     { 
      try 
      { 
       DALC.UpdateOrAddObject<PortfolioCorporateEntity>(pce); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Could not add Corporate Entity ID " + pce.CorporateEntity.CorporateEntityID.ToString()); 
      } 

     } 

Este es el procedimiento updateOrAdd en mi capa de acceso a datos de Nhibernate, llamado 10 veces para 10 objetos.

public void UpdateOrAddObject<T>(T workObject) 
{ 
    using (ITransaction tx = mSession.BeginTransaction) { 
     try { 
      mSession.SaveOrUpdate(workObject); 
      mSession.Flush(); 
      tx.Commit(); 
     } 
     catch (Exception ex) { 
      tx.Rollback(); 
      throw; 
     } 
    } 
} 

Sólo para aclarar este punto, la sesión se crea una instancia por el programa de llamada y pasa al objeto de capa de acceso a datos, constructor del que está por debajo.

public NHibernateDataProvider(ISession session) 
{ 
    mSession = session; 
} 

Esto funciona bien, excepto después de la excepción, dice que no descargue la sesión después de la excepción. No estoy seguro de por qué: la transacción se retiró muy bien y la base de datos debería estar lista para aceptar otra transacción, ¿no? ¿Qué estoy haciendo mal?

Respuesta

9

No se puede volver a utilizar una sesión de NHibernate después de lanzar una excepción. Quoting the documentation:

If the ISession throws an exception you should immediately rollback the 
transaction, call ISession.Close() and discard the ISession instance. 
Certain methods of ISession will not leave the session in a consistent state. 

Así que la respuesta es que no se puede hacer lo que estamos tratando de hacer. Necesita crear una nueva sesión y volver a probar las actualizaciones allí.

0

Gracias por la respuesta. Solo quería asegurarme de que esté bien hecho. Lo que está diciendo es que mi manejo de errores simplemente debe cambiarse a:

 foreach (var pce in pces) 
     { 
      try 
      { 
       DALC.UpdateOrAddObject<PortfolioCorporateEntity>(pce); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Could not add Corporate Entity ID " + pce.CorporateEntity.CorporateEntityID.ToString()); 

       session.Close(); 
       session = sessionsManager.GetSession(); 
       DALC.Session = session; 

      } 
     } 

Parece que esto funciona bien. Gracias.

+0

De lo que usted envió, que parece que va a trabajar. Realmente depende de la implementación de su clase DALC. –

+0

¿Hay alguna diferencia entre esta solución (session.Close/reopen) y la solución anterior con solo session.Clear()? – dataCore

6

que desactive la sesión y se continúa normalmente

 

ISession session = NHibernateHelper.Session; 
using (ITransaction transaction = session.BeginTransaction()) 
{ 
    try 
    { 
     session.Update(user, user.UserID); 
     transaction.Commit(); 
    } 
    catch (Exception ex) 
    { 
     transaction.Rollback(); 
     session.Clear(); 
     throw new DALException("Cannot update user", ex); 
    } 
} 
 
+0

¡Funciona! ¿Es esto una forma segura? Simplemente use "session.Clear()" para reestabilizar la sesión? – dataCore

+0

@sh_kamalh ¡Gracias amigo! También estaba enfrentando el mismo problema y buscando una solución simple como esta. – shahjahan

Cuestiones relacionadas