2016-08-03 96 views
0

Ich verwende Ninject, um meine Sitzung für eine Web-API/MVC-Anwendung zu verwalten. Der Code lautet wie folgt:Ninject 3.2 OnDeactivation nicht feuern Web API

Bind<ISession>().ToMethod(c => c.Kernel.Get<ISessionFactory>().OpenSession()) 
      .InRequestScope() 
      .OnActivation(s => s.BeginTransaction()) 
      .OnDeactivation((s) => 
      { 
       try 
       { 
        s.Transaction.Commit(); 
       } 
       catch (Exception e) 
       { 
        s.Transaction.Rollback(); 
       } 

       s.Close(); 
       s.Dispose(); 
      }); 
    } 

Der OnActivation Code korrekt genannt wird - wenn die Sitzung eine Transaktion begonnen wird injiziert wird. Wenn die Anforderung jedoch beendet wird, wird die Ondeaktivierung nicht aufgerufen. Daher kann ich Dinge aus der Datenbank abfragen, aber keine Änderungen festschreiben (es sei denn, ich übertrage die Transaktion anderswo).

Ich bin nicht wirklich sicher, warum die OnDeactivation nicht aufgerufen wird - fehle ich etwas in meinem Ninjizieren Setup?

Antwort

0

Aufruf Commit während OnDeactivation ist eine wirklich schlechte Idee, weil OnDeactivation wird immer genannt werden, auch wenn eine Ausnahme innerhalb der Business-Schicht geworfen wird. Im Falle eines Fehlers wollen Sie die Transaktion eindeutig nicht durchführen.

Sie sollten in Betracht ziehen, auf einer anderen Ebene zu begehen. This q/a spricht darüber ausführlicher und zeigt, wie man dieses Problem löst.

Beachten Sie auch, dass Ihr Code übermäßig ausführlich ist. Wenn Sie Dispose aufrufen, müssen Sie nicht Close aufrufen, und wenn Sie Dispose für eine nicht committed Transaktion aufrufen, wird die Transaktion automatisch zurückgesetzt. Sie können sogar den Stecker ziehen, die Datenbank wird automatisch eine nicht festgeschriebene Transaktion rückgängig machen. Mit anderen Worten, können Sie ganz einfach Ihren Code auf die folgende Vereinfachung:

.OnDeactivation((s) => 
{ 
    try 
    { 
     s.Transaction.Commit(); 
    } 
    finally 
    { 
     s.Dispose(); 
    } 
}); 

Sie können sogar die Dispose entfernen, wenn Sie die Verwendung des OnePerRequestHttpModule wie here machen. Dies reduziert den Code weiter zu:

.OnDeactivation(s => s.Transaction.Commit()); 

Aber auch hier OnDeactivation ist absolut der falsche Ort zu begehen.

+0

notiert - wird das Commit an anderer Stelle verschieben. mein Problem war, dass Ondeaktivierung nicht (immer) aufgerufen wurde - irgendeine Idee, warum das sein könnte? – Bonnotbh

+1

@Bonnotbh OnDeaktivierung und Entsorgung ist in Ninject normalerweise undefiniert. Ninject wird aufgeräumt, nachdem der Müll vom GC gesammelt wurde. Dies ist für Datenbankverbindungen oft nicht durchführbar. – Steven