web-dev-qa-db-fra.com

Référentiel générique avec EF 4.1 quel est le point

Alors que j'approfondis le DbContext, le DbSet et les interfaces associées, je me demande pourquoi vous auriez besoin d'implémenter un référentiel "générique" distinct autour de ces implémentations?

Il semble que DbContext et IDbSet fassent tout ce dont vous avez besoin et incluent l '"unité de travail" dans DbContext.

Suis-je en train de manquer quelque chose ici ou semble-t-il que les gens aiment ajouter une autre couche de dépendance sans raison?.

145
Code Jammr

Vous avez en fait raison. DbContext est une implémentation du modèle d'unité de travail et IDbSet est une implémentation du modèle de référentiel.

Les référentiels sont actuellement très populaires et surutilisés. Tout le monde les utilise simplement parce qu'il existe des dizaines d'articles sur la création d'un référentiel pour le cadre d'entité, mais personne ne décrit les défis liés à cette décision.

Les principales raisons d'utiliser le référentiel sont généralement:

  • Masquer EF du calque supérieur
  • Rendre le code mieux testable

La première raison est une sorte de pureté architecturale et une excellente idée que si vous rendez vos couches supérieures indépendantes d'EF, vous pouvez plus tard passer à un autre cadre de persistance. Combien de fois avez-vous vu une telle chose dans le monde réel? Cette raison rend le travail avec EF beaucoup plus difficile, car votre référentiel doit exposer un grand nombre de fonctionnalités supplémentaires englobant ce que EF autorise par défaut.

Dans le même temps, le code EF peut garder votre code mieux organisé et suivre la règle de séparation des préoccupations. Pour moi, cela peut être le seul véritable avantage du référentiel et de l'unité de travail, mais vous devez comprendre que le fait de suivre cette règle avec EF rendra peut-être votre code plus facile à gérer et à lire, mais dans l'effort initial de création de votre application, il sera beaucoup plus élevé et pour les petites applications, cela peut être une complexité inutile.

La deuxième raison est partiellement correcte. Le gros inconvénient d'EF est une architecture rigide qui peut être difficilement moquée, donc si vous voulez tester unitaire la couche supérieure, vous devez envelopper EF d'une manière ou d'une autre pour permettre de se moquer de son implémentation. Mais cela a de nombreuses autres conséquences que j'ai décrites ici .

Je suis le blog d'Ayende . Si vous avez déjà utilisé NHibernate, vous connaissez probablement ses articles. Ce type a récemment écrit plusieurs articles contre l'utilisation du référentiel avec NHibernate mais NHibernate est bien mieux moquable.

202
Ladislav Mrnka

Je me bats avec les mêmes problèmes, et la possibilité de se moquer des tests unitaires des couches EF est importante. Mais j'ai parcouru cet excellent article qui explique comment configurer l'EF 4.1 DbContext pour qu'il soit mockable en s'assurant que votre DbContext dérivé implémente une interface générique et expose IDbSet plutôt que DbSet. Puisque j'utilise une approche Database First, parce que notre base de données existe déjà, j'ai simplement modifié les modèles T4 utilisés pour générer mon DbContext dérivé pour le générer pour retourner les interfaces IDbSet, ainsi que dériver de mon interface générique. De cette façon, le tout peut être facilement moqué, et vous n'avez pas besoin d'implémenter votre propre unité de travail ou modèle de référentiel. Écrivez simplement votre code de service pour consommer votre interface générique, et lorsque vous passez au test unitaire, moquez simplement l'interface générique avec des données de test spécifiques et vous êtes prêt à partir.

http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/

21
Kendall Bennett

L'une des raisons de la création du référentiel est que vous pouvez masquer l'implémentation de DBSet et DbContext si vous décidez de passer d'EntityFramework à autre chose ou vice versa.

Par exemple, j'utilisais NHibernate et j'ai encapsulé tous les appels à ce framework dans mes classes de référentiel. Ils renvoient IEnumerable pour que leur soit "générique" et mes dépôts ont les opérations CRUD standard (mise à jour, suppression, etc.). Je suis depuis longtemps passé à Entity Framework. Ce faisant, je n'avais pas besoin de changer quoi que ce soit dans mes classes ViewModel ou au-delà, car ils pointaient vers mon référentiel - je n'avais qu'à changer l'intérieur de mon référentiel. Cela a rendu la vie beaucoup plus facile lors de la migration.

(J'ai utilisé NHibernate parce que nous nous connectons à l'ISeries, et à l'époque, il n'y avait aucune implémentation rentable utilisant EF avec l'ISeries. La seule disponible était de payer 12 000 $ à IBM pour leur DB2Connect)

5
user134363