2012-06-28 2 views
2

Vraiment, ma question est dans le titre ... Comment devrait-on gérer la session NHibernate à Nancy pour une session-par-requête? Si vous avez une bonne réponse pour cela en soi, foncez ... si vous avez besoin de plus de fond, la voici:Comment la session NHibernate doit-elle être gérée dans Nancy pour une session-par-requête?


Je suis habitué à utiliser un ActionFilter dans ASP.NET MVC ouvrir et fermer une session dans le contexte NHibernate au début et à la fin d'une requête Web. Ainsi, chaque opération de base de données dans le contexte d'une requête utilise la même session.

Je pensais que j'avais le même type de configuration dans mon nouveau projet utilisant Nancy, mais chaque fois qu'une session est nécessaire, une nouvelle est générée. Voilà comment je manipuler l'ouverture et la fermeture de la session dans mon programme d'amorçage (héritant de StructureMapBootstrapper):

protected override void RequestStartup(IContainer container, IPipelines pipelines, NancyContext context) 
{ 
    var sessionContainer = container.GetInstance<ISessionContainer>(); 
    pipelines.BeforeRequest.AddItemToStartOfPipeline(x => 
    { 
     sessionContainer.OpenSession(); 
     return x.Response; 
    }); 
    pipelines.AfterRequest.AddItemToEndOfPipeline(x => sessionContainer.CloseSession()); 
} 

Mon ISessionContainer est basé sur quelque chose de similaire à this site. Mon implémentation de ISessionContainer utilise le contexte de session de NHibernate pour obtenir la "session en cours".

À l'heure actuelle, lorsque j'essaie cela dans mon projet Nancy, une nouvelle session est renvoyée chaque fois que la propriété ISessionContainer.Session est demandée. Je pensais que c'était parce que les sessions basées sur les cookies ne sont pas activés par défaut à Nancy, alors j'ai ajouté à mon bootstrapper:

protected override void ApplicationStartup(IContainer container, IPipelines pipelines) 
{ 
    CookieBasedSessions.Enable(pipelines); 
} 

Pas de dés. Je reçois toujours une nouvelle session à chaque fois en demander un.

Mais, vraiment, je ne veux pas diagnostiquer mon problème. Je préfère entendre quelle est la manière standard de gérer la gestion de session NHibernate à Nancy.

Répondre

4

Dans mon Nancy port of the RestBucks sample j'utilise NHibernate dans un mouvement par demande.

Dans le bootstrapper from that sample j'ai la configuration suivante de NHibernate:

protected override void ApplicationStartup(IWindsorContainer container, 
              Nancy.Bootstrapper.IPipelines pipelines) 
{ 
    base.ApplicationStartup(container, pipelines); 
    pipelines.BeforeRequest += ctx => CreateSession(container); 
    pipelines.AfterRequest += ctx => CommitSession(container); 
    pipelines.OnError += (ctx, ex) => RollbackSession(container); 
    // Other startup stuff 
} 

private Response CreateSession(IWindsorContainer container) 
{ 
    var sessionFactory = container.Resolve<ISessionFactory>(); 
    var requestSession = sessionFactory.OpenSession(); 
    CurrentSessionContext.Bind(requestSession); 
    requestSession.BeginTransaction(); 

    return null; 
} 

private AfterPipeline CommitSession(IWindsorContainer container) 
{ 
    var sessionFactory = container.Resolve<ISessionFactory>(); 
    if (CurrentSessionContext.HasBind(sessionFactory)) 
    { 
    var requestSession = sessionFactory.GetCurrentSession(); 
    requestSession.Transaction.Commit(); 
    CurrentSessionContext.Unbind(sessionFactory); 
    requestSession.Dispose(); 
    } 
    return null; 
}  

private Response RollbackSession(IWindsorContainer container) 
{ 
    var sessionFactory = container.Resolve<ISessionFactory>(); 
    if (CurrentSessionContext.HasBind(sessionFactory)) 
    { 
    var requestSession = sessionFactory.GetCurrentSession(); 
    requestSession.Transaction.Rollback(); 
    CurrentSessionContext.Unbind(sessionFactory); 
    requestSession.Dispose(); 
    } 
    return null; 
} 

exactement comment vous voulez configurer votre session NHibernate sera probablement différent.

+0

Cela semble excellent. Je vais avec quelque chose comme ça. –

+0

Quelle implémentation de "CurrentSessionContext" utilisez-vous? Avec ThreadStaticSessionContext, il peut sembler que cela fonctionne, mais il s'agit d'une implémentation très fragile et qui se cassera sous une lourde charge si vous utilisez async/Tasks. Autant que je comprenne il n'y a aucune implémentation qui peut même théoriquement traiter des demandes asynchrones dans l'application de Nancy auto-hébergée. –

0

Dîners est un port de NerdDinner à Nancy et RavenDB et a récemment été examiné par Ayende ici http://ayende.com/blog/156609/reviewing-dinner-party-ndash-nerd-dinner-ported-to-ravendb-on-ravenhq?key=0c283ada-e5e8-4b7c-b76b-e9d27bfc0bf9

Je crois qu'il utilise des sessions par demande, parce que je me souviens indiquant comment pourrait-être utilisé un constructeur de module personnalisé. Jetez un oeil à la bootstrapper et la RavenAwareModuleBuilder

+0

Je regarde DinnerParty pour le moment. Ne pas le voir tout de suite. Vous souvenez-vous où il gérait les sessions? –

+0

pas regardé mais je devine le bootstrapper – TheCodeJunkie

Questions connexes