2010-05-01 11 views
23

Il y a plusieurs questions similaires à ce sujet, je n'ai toujours pas trouvé assez de raisons pour décider de la voie à suivre. La vraie question est, est-il raisonnable à abstract the NHibernate using a Repository pattern, ou not?NHibernate avec ou sans référentiel

Il semble que la seule raison derrière l'abstraction est de vous laisser une option pour remplacer NHibernate avec un ORM différent si nécessaire. Mais créer des dépôts et des requêtes d'abstraction semble ajouter une couche supplémentaire, et faire une grande partie de la plomberie à la main. Une option est d'utiliser exposer IQueryable<T> à la couche de gestion et utiliser LINQ, mais d'après mon expérience, le support LINQ n'est pas encore complètement implémenté dans NHibernate (les requêtes ne fonctionnent pas toujours comme prévu, et je déteste passer du temps sur le débogage un cadre). Bien que référencer NHibernate dans ma couche métier me fait mal aux yeux, c'est censé être une abstraction de l'accès aux données par lui-même, n'est-ce pas?

Que pensez-vous de cela?

+0

Comment ajouter un nouvel élément à la base de données avec juste linq? – Paco

+0

@Paco: Ajout d'un nouvel élément à la base de données est assez facile à résumer, je ne parle pas de cela. La requête est le problème réel, car il n'existe pas de moyen simple d'activer des requêtes complexes dans un référentiel sans codage suffisant. – Groo

Répondre

5

Bons quiestions. Je pensais aussi à eux il y a quelques jours.

En fait, essayez NHibernate 3.0 alpha (ou le tronc actuel), son nouveau fournisseur LINQ est beaucoup plus grand que les précédents. (Jusqu'à présent, je n'ai trouvé qu'une seule méthode qui ne fonctionne pas, mais il est possible de connecter votre propre mécanisme si vous rencontrez quelque chose qu'il ne supporte pas par défaut.) Je n'ai pas eu de problème (encore?) À utiliser le courant tronc. Vous pouvez trouver une version "nocturne" sur le site http://www.hornget.net/packages/, ainsi qu'une version FluentNHibernate. Fluent augmente vraiment votre productivité si vous savez comment l'utiliser. La communauté SO really helped me with that, aussi. Si vous êtes d'accord avec votre couche de gestion ayant une dépendance directe sur NHibernate, ou si vous écrivez une application plus petite qui reste maintenable sans ce type d'abstraction, vous pouvez vous passer du modèle de référentiel. Cependant, si vous le faites correctement, cela peut vous éviter beaucoup de codage redondant.

La raison de l'abstraction n'est pas seulement utile car vous pouvez ensuite remplacer NHibernate par un autre ORM, mais c'est une bonne pratique à cause d'un concept appelé Separation of Concerns. Votre couche logique métier ne doit pas se soucier de savoir comment accéder aux données avec lesquelles elle travaille. Cela facilite la maintenance de l'application ou de ses différentes couches, ce qui facilite également le travail d'équipe: si X crée la couche d'accès aux données et que Y écrit la logique métier, ils n'ont pas besoin de connaître le travail des autres en détail.

Exposer un IQueryable<T> est une très bonne idée, et c'est exactement ce que font actuellement de nombreuses implémentations de référentiel. (Et moi aussi, bien que je préfère l'écrire dans une classe statique.) Et bien sûr, vous devrez exposer certaines méthodes pour insérer ou mettre à jour une entité, ou des méthodes pour commencer et valider des transactions, si vous le souhaitez. (Le BeginTransaction devrait juste retourner un IDisposable pour éviter les fuites sur une interface NHibernate, et ce sera très bien.)

je peux vous donner quelques directions: consultez les implémentations de SharpArchitecture ou FubuMVC Contrib pour obtenir quelques idées sur comment faites c'est vrai, et c'est how I solved it.

+0

Merci pour la réponse. En fait, ce que je voulais dire, c'est que l'utilisation de HNibernate pour interroger directement les données ne devrait pas exposer de manière significative l'implémentation de la base de données à la couche de gestion, une fois que vous aurez mappé ces deux modèles ensemble. Je crois que c'était l'idée originale derrière le concept ORM. Personnellement, la vérité est que je ne veux pas l'utiliser directement, mais un modèle de dépôt (si je n'expose pas IQueryable) nécessite un codage supplémentaire. Utiliser Linq serait adorable, si c'était fiable. Peut-être que je vais essayer la version alpha :). – Groo

+0

Je n'ai eu aucun problème (encore?) À utiliser le tronc actuel. Mise à jour ma réponse – Venemo

1

Je dirais simplement un grand OUI! avoir un motif Repository, gardez les choses abstraites!

1

Personnellement, je préfère toujours extraire le NHibernate dans un modèle de référentiel. La raison en est que je pourrais encore avoir d'autres implémentations du référentiel pour la mise en cache, se moquant des tests unitaires, etc. Et j'utilise aussi IQueryable avec mon référentiel, bien que je fasse IRepository étendre IQueryable plutôt qu'exposer une propriété sur IRepository de type IQueryable.

Un autre point de dépôt. Certaines personnes suggèrent de ne pas le rendre générique et d'avoir l'identification de type au niveau de la méthode (c'est-à-dire repository.Load). Ceci, cependant, suppose qu'il y aura un référentiel unique qui sait comment traiter tous les types. Je ne suis pas un grand fan de cette notion d'un seul dépôt monolithique. Que faire si vous traitez plusieurs bases de données? Ou plusieurs mécanismes de persistance? Ou certains types de données restent assez statiques et peuvent être mis en cache, mais d'autres ne le peuvent pas. C'est pourquoi j'aime une instance de référentiel distincte pour chaque type.