2016-08-03 1 views
0

J'utilise ninject pour gérer ma session pour une application Web API/MVC. Le code est le suivant:Ninject 3.2 OnDeactivation ne déclenche pas l'API Web

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(); 
      }); 
    } 

Le code OnActivation est appelé correctement - lorsque la session est injectée une transaction est commencée. Cependant, lorsque la requête se termine, l'ondeactivation n'est pas appelée. Par conséquent, je peux interroger des choses à partir de la base de données mais ne pas valider les modifications (à moins que je ne commette la transaction ailleurs).

Je ne suis pas vraiment sûr pourquoi le OnDeactivation n'est pas appelé - est-ce que je manque quelque chose dans mon installation de ninject?

Répondre

0

Appel Commit au cours OnDeactivation est une très mauvaise idée, car OnDeactivation se toujours être appelé, même si une exception est levée à partir de la couche d'affaires. En cas d'erreur, vous ne voulez manifestement pas valider la transaction.

Vous devriez envisager de valider à un niveau différent. This q/a en parle plus en détail et montre comment résoudre ce problème.

Notez également que votre code est trop verbeux. Si vous appelez Dispose, vous n'avez pas besoin d'appeler Close et si vous appelez Dispose pour une transaction non validée, la transaction est automatiquement annulée. Vous pouvez même tirer la prise, la base de données annulera automatiquement une transaction non validée. En d'autres termes, vous pouvez facilement simplifier votre code à ce qui suit:

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

Vous pouvez même retirer le Dispose lorsque vous utilisez du OnePerRequestHttpModule comme décrit here. Cela réduit le code supplémentaire à:

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

Mais encore une fois, OnDeactivation est tout à fait au mauvais endroit à commettre.

+0

noté - déplacera le commit ailleurs. mon problème était que la désactivation n'était pas appelée (jamais) - aucune idée pourquoi cela pourrait être? – Bonnotbh

+1

@Bonnotbh OnDeactivation et l'élimination est généralement non déterministe dans Ninject. Ninject nettoiera après la collecte des ordures par le GC. Ceci n'est souvent pas réalisable pour les connexions à la base de données. – Steven