2009-11-30 6 views
8

Ich entwickle eine ASP.NET MVC-Webanwendung unter .NET 3.5, NHibernate und gehostet auf Windows Azure. Wenn die Webanwendung von der lokalen Entwicklungsumgebung ausgeführt wird, funktioniert sie einwandfrei. Wenn ich es jedoch nach Windows Azure verschiebe, endet jede von der MVC-Webrolle durchgeführte Einfügung mit der unten aufgeführten Ausnahme.Spülen Sie die Sitzung nicht, nachdem eine Ausnahme auftritt - NHibernate

Irgendeine Idee, was ist los mit meiner NHibernate Logik? (Könnte das Session-Management, nicht sicher)

[AssertionFailure: null id in Lokad.Translate.Entities.User Eintrag (nicht die Session spülen, nachdem eine Ausnahme auftritt)] NHibernate.Event.Default. DefaultFlushEntityEventListener.CheckId (Object obj, IEntityPersister persister, Objekt-ID, EntityMode entityMode) +292 NHibernate.Event.Default.DefaultFlushEntityEventListener.GetValues ​​(Object Einheit, EntityEntry Eintrag, EntityMode entityMode, Boolean mightBeDirty, ISessionImplementor Sitzung) +93 NHibernate.Event .Default.DefaultFlushEntityEventListener.OnFlushEntity (FlushEntityEvent-Ereignis) +158 NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities (FlushEvent-Ereignis) +469 NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions (FlushEvent Ereignis) +339 NHibernate.Event.Default.DefaultFlushEventListener.OnFlush (FlushEvent Ereignis) +85 NHibernate.Impl.SessionImpl.Flush() +275 NHibernate.Transaction.AdoTransaction .Commit() +236 Lokad.Translate.Repositories.PageRepository.Create (Seite Seite) Lokad.Translate.Controllers.PagesController.Create (Seite Seite) lambda_method (ExecutionScope, Controller, Object []) +69 -System. Web.Mvc.ReflectedActionDescriptor.Execute (ControllerContext controllerContext, IDictionary 2 parameters) +251 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary 2 Parameter) +31 System.Web.Mvc. <> c__DisplayClassa.b__7() +88 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter (IActionFilter Filter, ActionExecutingContext Vorkontext, Func 1 continuation) +534 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList 1 Filter, ActionDescriptor actionDescriptor, IDictionary`2 Parameter) +312 System.Web.Mvc.ControllerActionInvoker. InvokeAction (Controllercontroller, String action) +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 (IExecutionStep-Schritt, Boolean & completedSynchronously) +177

Bitte beachte, dass ich _session.FlushMode = FlushMode.Commit; verwende und dass die User in einem benutzerdefinierten verwendet wird 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]; 
     } 
    } 
} 

Antwort

4

Ich habe endlich eine Lösung für mein eigenes Problem gefunden. Falls die Leute interessiert sind, schreibe ich hier die Lösung.

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"}; 
     } 
    } 
} 

Im Grunde, was passiert ist, dass die RoleProvider Repository nicht die gleiche Lebensdauer als herkömmliche in-view/in-Controller-Repositorys zu haben scheinen. Dies hat zur Folge, dass zum Zeitpunkt des Aufrufs des RoleProvider die NHibernate-Sitzung bereits abgesetzt wurde, was die oben beschriebene Ausnahme verursacht.

Ich habe den Code durch den folgenden hier oben ersetzt. Dieser hat sein eigenes NHibernate Sitzungsmanagement und funktioniert gut.

18

Sie sollten niemals Ausnahmen fangen und sie während einer NHibernate Transaktion ignorieren.

Ich versuche zu erklären, warum.

Es könnte Ausnahmen geben, die zum Beispiel durch Einschränkungen in der Datenbank verursacht werden. (Dies kann auch durch Zuordnungsprobleme verursacht werden, Ausnahmen, die von Eigenschaften ausgelöst werden, oder irgendetwas anderes.) NHibernate versucht, den Status im Speicher mit der Datenbank zu synchronisieren. Dies geschieht beim Commit - und manchmal vor den Abfragen, um sicherzustellen, dass Abfragen auf tatsächlichen Daten ausgeführt werden. Wenn diese Synchronisierung fehlschlägt, der Zustand in der Datenbank ist etwas zufälliger, einige Änderungen werden beibehalten, andere nicht. Das einzige, was Sie in einem solchen Fall tun können, ist das Schließen der Sitzung.

Berücksichtigen Sie, dass Entscheidungen und Berechnungen in Ihrem Code auf Werten im Speicher basieren. Aber - im Falle einer ignorierten Ausnahme sind diese Werte nicht die Werte in der Datenbank, sie werden niemals da sein. Deine Logik wird also entscheiden und auf 'Fantasy-Daten' rechnen.

Übrigens, ist es nie eine gute Idee, eine Ausnahme zu fangen (untypisiert) und ignorieren sie. Sie sollten die Ausnahmen, die Sie behandeln, immer kennen und sicher sein, dass Sie fortfahren können.

Was Sie hier tun, schluckt Programmierfehler. Glauben Sie mir, das System wird nicht stabiler sein. Die Frage ist nur: bemerken Sie den Fehler, wenn es auftritt, oder ignorieren Sie es dort und sogar persist das Ergebnis des Fehlers in die Datenbank? Wenn Sie Letzteres tun, müssen Sie nicht überrascht sein, wenn Ihre Datenbank inkonsistent ist und andere Fehler auftreten, wenn Sie versuchen, die Daten von der Datenbank zu erhalten. Und Sie werden nie den Code finden, der die eigentliche Ursache des Fehlers ist.

+0

Hallo Stefan, vielen Dank für Ihre ausführliche Erklärung. Ich habe endlich eine Lösung gefunden. Das Problem hat nichts mit Ihrer Erklärung zu tun, aber trotzdem ist es ein großartiger Punkt. –

+0

Vielen Dank für so detaillierte Erklärung Ich hatte den gleichen Fehler und es wurde durch Schlucken NHibernate Ausnahme verursacht. Ich habe viel Zeit gespart, indem ich deinen Beitrag gelesen habe. – Vladimirs

0

Diese Ausnahme kann auftreten, wenn Spaltennamen reservierte Worte enthalten (zum Beispiel Verwendung Status als Spaltenname und es wird unmöglich zu speichern)

Verwandte Themen