2012-07-06 2 views
8

Je commence à créer une application, et je prévois d'utiliser ServiceStack. Je veux juste savoir quelles sont les meilleures pratiques/bonnes approches pour manipuler NHibernate ISession ou d'autres objets de session spécifiques au contexte "par requête".ServiceStack NHibernate Session par demande

Je pensais que l'enregistrement d'un ISessionFactory dans le Cio comme:

container.Register<ISessionFactory>(sessionFactory); 

Et en cas de besoin obtenir un nouvel objet Session ... Ou peut-être fournir directement l'objet de la session:

container.Register<ISession>(c => sessionFactory.OpenSession()).ReusedWithin(ReuseScope.None); 

Ou l'une des poignées l'ISession et une transaction par défaut via l'événement Global.asax BeginRequest:

protected void Application_BeginRequest(object sender, EventArgs e) 
{ 
    var session = factory.OpenSession(); 
    ITransaction itrans = session.BeginTransaction(); 
    Context.Items.Add("session", session); 
    Context.Items.Add("trans", itrans); 
} 

Donc, je suis un peu perdu, quelles sont les meilleures pratiques, étant donné les technologies ci-dessus, ou similaires, comme EF ou un autre cadre Rest-Services?

Merci à l'avance

Répondre

3

Voir ce billet de blog pour un exemple complet de l'utilisation optimale ServiceStack et NHibernate ensemble:

http://www.philliphaydon.com/2012/06/using-nhibernate-with-servicestack/ Voici l'exemple apphost utilisé dans le post ci-dessus:

public class Global : HttpApplication 
{ 
    public class SampleServiceAppHost : AppHostBase 
    { 
     private readonly IContainerAdapter _containerAdapter; 
     public SampleServiceAppHost(ISessionFactory sessionFactory) 
      : base("Service Stack with Fluent NHibernate Sample", typeof(ProductFindService).Assembly) 
     { 
      base.Container.Register<ISessionFactory>(sessionFactory); 
     } 

     public override void Configure(Funq.Container container) 
     { 
      container.Adapter = _containerAdapter; 
     } 
    } 

    void Application_Start(object sender, EventArgs e) 
    { 
     var factory = new SessionFactoryManager().CreateSessionFactory(); 

     (new SampleServiceAppHost(factory)).Init(); 
    } 
} 
4

Créer une session par requête en utilisant un HttpHandler est la façon la plus courante de le faire que j'ai trouvée. Ayende a expliqué que créer une session est vraiment léger. http://ayende.com/blog/4123/what-is-the-cost-of-opening-a-session

Ayende a en fait une série de postes où il construit progressivement la solution d'accès aux données. Chaque poste explique pourquoi il a fait ce qu'il a fait et quelles questions doivent être résolues avec les mesures prises jusqu'à présent. Commencez ici: http://ayende.com/blog/4803/refactoring-toward-frictionless-odorless-code-the-baseline

Enfin, http://nhforge.org/blogs/nhibernate/archive/2011/03/03/effective-nhibernate-session-management-for-web-apps.aspx

Toutes ces variations sont de la session par demande. La chose commune à tous n'est pas d'avoir à se soucier manuellement de la création d'une session/transaction. Ils vont commettre/rollback les transactions automatiquement.

3

Je sais que c'est une vieille question, mais je me suis dit que j'irais de l'avant et que je montrerais à quiconque qui est toujours intéressé par une autre réponse comment nous l'avons fait.

Nous utilisons le ServiceRunner dans la nouvelle API ServiceStack ainsi:

public class BaseServiceRunner<TRequest> : ServiceRunner<TRequest> 
{ 
    public BaseServiceRunner(AppHost appHost, ActionContext actionContext) 
    : base(appHost, actionContext) { } 

    public override void OnBeforeExecute(IRequestContext requestContext, TRequest request) 
    { 
     var req = request as MyRequestType; 

     if(req == null) 
      base.OnBeforeExecute(requestContext, request); 

     var factory = TryResolve<NHibernate.ISessionFactory>(); 
     var session = factory.OpenSession(); 
     var trans = session.BeginTransaction(IsolationLevel.ReadCommitted); 

     requestContext.SetItem("session", session); 
     requestContext.SetItem("transaction", trans); 
    }   

    public override object OnAfterExecute(IRequestContext requestContext, object response) 
    { 
     var trans = requestContext.GetItem("transaction") as ITransaction; 
     if (trans != null && trans.IsActive) 
      trans.Commit(); 

     var session = requestContext.GetItem("session") as ISession; 
     if (session != null) 
     { 
      session.Flush(); 
      session.Close(); 
     } 

     return base.OnAfterExecute(requestContext, response); 
    } 

    public override object HandleException(IRequestContext requestContext, TRequest request, Exception ex) 
    { 
     var req = request as MyRequestType; 
     if(req != null) 
     { 
      var trans = requestContext.GetItem("transaction") as ITransaction; 
      if (trans != null && trans.IsActive) 
       trans.Rollback(); 

      var session = requestContext.GetItem("session") as ISession; 
      if (session != null) 
      { 
       session.Flush(); 
       session.Close(); 
      } 
     } 
     return base.HandleException(requestContext, request, ex); 
    }   
} 
+1

Pouvez-vous s'il vous plaît expliquer comment vous avez utilisé ce? La documentation de ServiceStack n'a vraiment aucun sens sur la façon d'utiliser ces ServiceRunners. – slashp

+0

J'ai ajouté du code à ajouter dans votre hôte d'application. Vous ne savez pas comment utiliser le service Coureur du service. –

+0

Juste vu les demandes pour plus de détails, pourrait être trop tard pour être utile, mais peut-être quelqu'un d'autre veut savoir. 'code' public class AppHost: AppHostBase { public AppHost(): base (" Service ", typeof (AccessService).Assemblée) {} public override vide Configurer (conteneur conteneur) {} public override IServiceRunner CreateServiceRunner (ActionContext ActionContext) {return new BaseServiceRunner (ce, ActionContext); } 'code' –