2012-05-10 9 views
5

Ich habe eine Aktion auf meiner MVC-Anwendung, die eine id haben und gibt den Namen einer Person zurück.NHibernate - Best Practice für nur wählen

Was ist die beste Vorgehensweise dafür? Ich folge NHProf Tipps, aber Code klingt ein wenig seltsam oder etwas für mich.

using (var session = Helper.SessionFactory.OpenStatelessSession()) 
{ 
    using (var tran = session.BeginTransaction(IsolationLevel.ReadCommitted)) 
    { 
     return session.Query<Person>().Where(x => x.Id == id).Select(x => x.Name).SingleOrDefault(); 
     tran.Rollback(); 
    } 
} 
+0

Ich kann nicht verstehen, warum es eine Transaktion vorschlagen ... –

+0

was wollen Sie wissen? –

+1

Ich würde 'OpenStatelessSession' nicht verwenden, da die zustandslose Sitzung für Massenszenarien ist und den L1-Cache ignoriert. Anstatt eine linq-Abfrage zu machen, würde ich einfach '.Load (1)' oder '.Get (1)' nennen, die mehr als eine linq-Abfrage beabsichtigen. – Andreas

Antwort

4

Die NHProf alert Seite erklärt es ganz gut denke ich -

http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions

es ist im Grunde sagen, wenn Sie eine „implizite Transaktion“ und Auto nicht Transaktionen selbst verwalten, wird die Datenbank erstellen -commit für jede Anweisung, einschließlich Abfragen. Das Missverständnis ist, dass Transaktionen nur für Einfüge-/Aktualisierungsoperationen nützlich sind.

In Ihrem obigen Beispiel ist es kein großes Problem, da Ihre Transaktion sowieso nur eine einzige Anweisung ausführt. Wenn Ihre Methode mehrere Anweisungen ausführt, empfiehlt es sich jedoch, sie in eine Transaktion zu integrieren.

+0

OK, aber für einfache Methoden sollte ich NHProf folgen und eine Transaktion erstellen oder nicht? – Zote

+1

Die Antwort ist nur teilweise wahr, Sie sollten Ihre Datenbankabfrage in einer Transaktion immer _____verwinden und in der Tat wäre es ein Problem, selbst wenn Sie eine einzelne Anweisung ausführen. Implizite Transaktionen sind teuer! und NH wird den L2-Cache ohne eine Transaktion nicht verwenden. – Andreas

-1

Das Folgende ist, wie ich diesen Ansatz wählen:

using (var session = Helper.SessionFactory.OpenStatelessSession()) 
    using (var tran = session.BeginTransaction(IsolationLevel.ReadCommitted)) 
    { 
     try 
     { 
      string personName = session.Query<Person>() 
      .Where(x => x.Id == id) 
      .Single(x => x.Name); 

      tran.Commit(); 
      return personName; 
     } 
     catch(Exception ex) 
     { 
      // handle exception 
      tran.Rollback(); 
     } 
    } 

Diese SO Antwort gibt gute Ratschläge mit der Transaktion zu tun verpflichtet:

NHibernate - Is ITransaction.Commit really necessary?

Mit Bezug auf Ihre LINQ ist dies ein interessanter Artikel darüber, wie Abfragen nicht mit der Erweiterungsmethode-Stilsyntax ausgeführt werden können:

http://compiledexperience.com/blog/posts/how-not-to-use-linq

+0

-1 für alles zu fangen, redundante Arbeit (mit und fangen fangen). – Andreas

+0

@Andreas, soweit mir bekannt ist, hat keine Möglichkeit, eine ausgelöste Ausnahme zu verarbeiten, und die Wahl besteht darin, einen redundanten Versuch zu verwenden oder manuell zu beseitigen. Wie würden Sie in diesem Fall die Fehlerbehandlung implementieren, da es mehrere Layer gibt, die einen Fehler auslösen könnten (NHibernate, ADO.NET, LINQ). –

+2

http://stackoverflow.com/questions/6418992/is-it-a-better-practice-to-explicitly-call-transaction-rollback-or-let-an-except und für Ausnahmen http://stackoverflow.com/questions/426346/is-this-a-bad-practice-to-catch-eine-unspezifische-ausnahme-wie-system-exceptionio http://stackoverflow.com/questions/114658/catching-base- exception-class-in-net http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx und sagen Sie mir nicht, dass Sie stackoverflows, nicht genügend Arbeitsspeicher richtig behandeln können exc mit deinem 'tran.Rollback();'. – Andreas

0

erstellen Sie nicht mehrere Sitzungen über eine HTTP-Anforderung, idealerweise müssen Sie eine Sitzung und eine entsprechende Transaktion im Anforderungsbereich öffnen und diese Sitzung für alle Ihre Aktionen verwenden.

Hier ist ein Blogpost zu erklären, wie es zu erreichen: http://hackingon.net/post/NHibernate-Session-Per-Request-with-ASPNET-MVC.aspx

Ich würde die Verwendung eines IOC-Container vorschlagen und eine Klasse erstellen, die die Sitzung für Sie und den Umfang dieser Klasse auf die Anfrage Rahmen schafft.

Es gibt viele Ressourcen im Internet, dieses Problem zu nähern .. Google it ..

+0

Während eine Sitzung pro Anfrage ein guter Rat ist, ist es keine feste Regel, und eine Transaktion pro Anfrage zu haben ist ein schlechter Rat, schlicht und einfach. – Spivonious