2010-04-19 8 views
2

Je viens de commencer à apprendre NHibernate.Couplage ASP.NET MVC et NHibernate

Au cours des derniers mois, j'ai utilisé IoC/DI (structuremap) et le modèle de dépôt, ce qui a rendu mes applications beaucoup plus lâches et plus faciles à tester. Lors de la commutation de ma couche de persistance à NHibernate, j'ai décidé de rester avec mes dépôts. Actuellement, je crée une nouvelle session sur chaque appel de méthode, mais bien sûr cela signifie que je ne peux pas bénéficier d'un chargement paresseux.

Par conséquent, je souhaite implémenter session-per-request mais ce faisant, cela rendra mon projet web dépendant de NHibernate (ce n'est peut-être pas une si mauvaise chose?). Je prévoyais d'injecter ISession dans mes dépôts et de créer et d'éliminer des sessions sur des événements de demande de début/fin d'appel (voir http://ayende.com/Blog/archive/2009/08/05/do-you-need-a-framework.aspx)

Est-ce une bonne approche? Vraisemblablement, je ne peux pas utiliser session-per-request sans faire référence à NHibernate dans mon projet web? Avoir le projet web dépendant de NHibernate m'invite à ma (prochaine) question suivante - pourquoi même s'embêter avec le référentiel? Puisque mon application web appelle des services qui parlent aux dépôts, pourquoi ne pas abandonner les dépôts et simplement ajouter mon code de persistance NHibernate dans les services? Et enfin, est-il vraiment nécessaire de se diviser en autant de projets? Un projet web et un projet d'infrastructure sont-ils suffisants?

Je me rends compte que je me suis un peu éloigné de ma question initiale, mais il semble que tout le monde semble avoir sa propre opinion sur ces sujets. Certaines personnes utilisent le modèle de référentiel avec NHibernate, d'autres non. Certaines personnes collent leurs fichiers de mapping avec les classes associées, d'autres ont un projet séparé pour cela.

Un grand merci, Ben

+0

Je viens de commencer à utiliser MVC ... et honnêtement, je ne vois aucune utilité pour le chargement paresseux dans la vue. Je m'assure juste que les champs appropriés sont chargés avec impatience. Les choses de l'OMI sont beaucoup plus simples si la portée de la session reste à l'intérieur de la méthode d'action. – dotjoe

+0

Il peut ne pas être utile dans la vue, mais il est certainement utile dans les services utilisés pour créer le modèle de vue, et il permet d'économiser de la complexité dans la couche du référentiel. Un exemple serait un ordre qui a beaucoup de lignes de commande.Sur une page affichant une liste ou des commandes, je ne voudrais pas charger avec impatience chaque ligne de commande. Cependant, quand j'ai percé dans l'ordre je voudrais les lignes de commande. Utiliser un chargement paresseux me permet d'avoir un seul référentiel d'Ordres et signifie que je n'ai pas besoin de méthodes de dépôt supplémentaires pour charger les lignes de commande. –

+0

Juste une note sur l'étendue de la session - qu'en est-il d'une page contenant plusieurs vues partielles rendues par différentes actions (par exemple en utilisant RenderAction). Sûrement il serait préférable pour ceux-ci d'enregistrer la même session (par demande de page) que d'avoir une session par action? –

Répondre

1

je ne ferais pas la logique métier dépendant de NHibernate. J'ai écrit un (plus ou moins simple) classe pour créer la session dans un contexte:

using (TransactionService.CreateTransaction()) 
{ 
    // use repository here 

    // rollback on exception, only commit when reach this last line: 
    TransactionService.Commit(); 
} 

Vous obtenez juste une IDisposable, vous n'avez pas besoin de connaître la session.

Les référentiels reçoivent une API pour accéder à la session. Par exemple:

// example repository implementation 
public Entity Get(Guid id) 
{ 
    return SessionProvider.Session.Get<Entity>(id); 
} 

Pour mettre en œuvre, je mets la session dans une variable ThreadStatic, qui est initialisé dans CreateTransaction et retourné par SessionProvider.Session.

+0

@Stefan, pouvez-vous expliquer comment cela fonctionne avec la session par demande. Comment/où créez-vous et disposez-vous de la session? –

+0

Je crée la session dans 'TransactionService.CreateTransaction'. là je renvoie une classe minuscule qui implémente 'IDisposable' et appelle le' TransactionService' dans Dispose (j'envoie en fait un événement qui est enregistré par 'TransactionService' quand il crée cet objet.) Là la session est fermée. Lorsque votre requête arrive, vous ouvrez la transaction en utilisant 'TransactionService.CreateTransaction'. Alors c'est là. –

+0

Voulez-vous partager le code de votre TransactionService? Aucune infraction, mais le code ci-dessus ne m'aide pas vraiment en l'état. –

1

Jetez un oeil à S#arp Architecture. Il répond à tout ce dont vous avez besoin, y compris, comment séparer la couche de données (NHibernate), la couche Web et la logique métier.