2009-11-30 10 views
8

Estoy desarrollando una aplicación web ASP.NET MVC en .NET 3.5, NHibernate y alojada en Windows Azure. Cuando, la aplicación web se ejecuta desde el tejido de desarrollo local, funciona bien. Sin embargo, cuando lo muevo a Windows Azure, cada inserción realizada desde el rol web de MVC termina con la excepción que se detalla a continuación.No vacíe la sesión después de una excepción - NHibernate

¿Alguna idea de cuál es el problema con mi lógica de NHibernate? (Que podría ser la gestión de sesiones, no estoy seguro)

[AssertionFailure: id nulo en la entrada Lokad.Translate.Entities.User (No echar la sesión después de que ocurre una excepción)] NHibernate.Event.Default. DefaultFlushEntityEventListener.CheckId (Object obj, IEntityPersister persister, ID del objeto, EntityMode EntityMode) +292 ( NHibernate.Event.Default.DefaultFlushEntityEventListener.GetValues ​​entidad objeto, entrada EntityEntry, EntityMode EntityMode, Boolean mightBeDirty, sesión ISessionImplementor) 93 NHibernate.Event .Default.DefaultFlushEntityEventListener.OnFlushEntity (evento FlushEntityEvent) +158 NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities (evento FlushEvent) +469 NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions (FlushEvent evento) 339 (evento FlushEvent) NHibernate.Event.Default.DefaultFlushEventListener.OnFlush 85 NHibernate.Impl.SessionImpl.Flush() 275 NHibernate.Transaction.AdoTransaction .Commit() 236 Lokad.Translate.Repositories.PageRepository.Create (página) Lokad.Translate.Controllers.PagesController.Create (página) lambda_method (ExecutionScope, ControllerBase, Object []) 69 sistema. Web.Mvc.ReflectedActionDescriptor.Execute (ControllerContext controllerContext, IDictionary 2 parameters) +251 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary 2 parámetros) +31 System.Web.Mvc. <> c__DisplayClassa.b__7() 88 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter (filtro IActionFilter, ActionExecutingContext preContext, Func 1 continuation) +534 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList 1 filtros, ActionDescriptor ActionDescriptor, parámetros IDictionary`2) 312 System.Web.Mvc.ControllerActionInvoker. InvokeAction (ControllerContext ControllerContext, cadena actionName) 856 System.Web.Mvc.Controller.ExecuteCore() 185 System.Web.Mvc.MvcHandler.ProcessRequest (HttpContextBase HttpContext) 221 System.Web.CallHandlerExecutionStep.System.Web .HttpApplication.IExecutionStep.Execute() +586 System.Web.HttpApplication.ExecuteStep (paso IExecutionStep, Boolean & completado de forma sincrónica) +177

Tenga en cuenta que estoy usando _session.FlushMode = FlushMode.Commit; y que el User se utiliza en una costumbre RoleProvider

public class SimpleRoleProvider : RoleProvider 
{ 
    readonly UserRepository Users = new UserRepository(); 

    public override string[] GetRolesForUser(string username) 
    { 
     try 
     { 
      var user = Users.Get(username); 

      // no role if user is not registered 
      if (null == user) return new string[0]; 

      // default role for registered user 
      return user.IsManager ? new[] { "Manager", "User" } : new[] { "User" }; 
     } 
     catch (Exception) 
     { 
      // role should not fail in case of DB issue. 
      return new string[0]; 
     } 
    } 
} 

Respuesta

4

Finalmente he encontrado una solución a mi propio problema. En caso de que las personas estén interesadas, estoy publicando la solución aquí.

public class SimpleRoleProvider : RoleProvider 
{ 
    // isolated session management for the RoleProvider to avoid 
    // issues with automated management of session lifecycle. 

    public override string[] GetRolesForUser(string username) 
    { 
     using (var session = GlobalSetup.SessionFactory.OpenSession()) 
     { 
      var users = new UserRepository(session); 
      var user = users.Get(username); 

      // no role if user is not registered 
      if (null == user) return new string[0]; 

      // default role for registered user 
      return user.IsManager ? new[] {"Manager", "User"} : new[] {"User"}; 
     } 
    } 
} 

Básicamente lo que estaba sucediendo es que el repositorio RoleProvider no parecen tener el mismo ciclo de vida de regulares en-vista-controlador/en repositorios. Como resultado, en el momento en que se llama al RoleProvider, la sesión NHibernate ya ha sido eliminada, causando la excepción que se observa aquí arriba.

He reemplazado el código por el siguiente aquí arriba. Éste tiene su propia administración de sesiones NHibernate, y termina funcionando bien.

18

Nunca se debe capturar las excepciones y hacer caso omiso de ellos durante una transacción NHibernate.

Intento explicar por qué.

Podría haber excepciones, por ejemplo, causadas por restricciones en la base de datos. (También podría ser causado por problemas de asignación, excepciones arrojadas por propiedades o cualquier otra cosa). NHibernate intenta sincronizar el estado en la memoria con la base de datos. Esto se realiza en la confirmación, y en ocasiones antes de las consultas, para garantizar que las consultas se realicen con los datos reales. Cuando esta sincronización falla, el estado en la base de datos es algo aleatorio, algunos cambios se conservan, otros no. Lo único que puede hacer en tal caso es cerrar la sesión.

Tenga en cuenta que las decisiones y los cálculos en su código se basan en los valores en la memoria. Pero, en el caso de una excepción ignorada, estos valores no son los valores en la base de datos, nunca estarán allí. Entonces su lógica decidirá y calculará en 'fantasía-datos'.

Por cierto, nunca es una buena idea detectar cualquier excepción (sin tipo) e ignorarlas. Siempre debe saber las excepciones que maneja y asegúrese de poder continuar.

Lo que estás haciendo aquí es tragar errores de programación. Créanme, el sistema no será más estable. La pregunta es única: ¿observa el error cuando ocurre, o lo ignora allí e incluso persisten el resultado del error en la base de datos? Cuando haces esto último, no debes sorprenderte cuando tu base de datos es inconsistente y surgen otros errores cuando tratas de obtener los datos de la base de datos. Y nunca encontrarás el código que es la causa real del error.

+0

Hola Stefan, muchas gracias por su explicación detallada. Finalmente encontré una solución. El problema no estaba relacionado con tu explicación, pero aún así es un gran punto. –

+0

Muchas gracias por la explicación tan detallada que tuve el mismo error y fue causado al tragar la excepción de NHibernate. Ahorré mucho tiempo leyendo tu publicación. – Vladimirs

0

Esta excepción puede ocurrir si sus nombres de columna incluyen las palabras reservadas (por ejemplo, el estado de su uso como un nombre de columna y se convertirá en imposible salvar)

Cuestiones relacionadas