2009-02-06 5 views
18

Je commence un nouveau projet et j'ai décidé d'essayer d'incorporer des patterns DDD et d'inclure Linq to Entities. Quand je regarde le ObjectContext d'EF il semble exécuter les fonctions des modèles Repository et Unit of Work:Entity Framework en tant que référentiel et UnitOfWork?

Référentiel en ce sens que l'interface de niveau de données sous-jacente est extraite de la représentation d'entité et je peux demander et enregistrer des données à travers ObjectContext.

unité de travail dans le sens que je peux écrire mes insertions/mises à jour du ObjectContext et les exécuter en un seul coup quand je fais un SaveChanges().

Il semble superflu de mettre une autre couche de ces motifs sur le dessus de l'EF ObjectContext? Il semble également que les classes Model puissent être incorporées directement au-dessus des entités générées EF en utilisant 'partial class'.

Je suis nouveau à DDD alors s'il vous plaît laissez-moi savoir s'il me manque quelque chose ici.

Répondre

17

Je ne pense pas que le Entity Framework est une bonne mise en œuvre du référentiel, parce que:

  • Le contexte de l'objet est suffisamment abstrait pour faire des tests de bonne unité des choses qui y font référence, puisqu'il est lié à l'accès DB. Avoir une référence IRepository fonctionne à la place beaucoup mieux pour créer des tests unitaires.
  • Lorsqu'un client a accès à ObjectContext, le client peut faire à peu près tout ce qu'il veut. Le seul vrai contrôle que vous avez sur ce point est de rendre certains types ou propriétés privés. Il est difficile de mettre en œuvre une bonne sécurité des données de cette façon.
  • Sur un modèle non trivial, ObjectContext est insuffisamment abstrait. Vous pouvez, par exemple, associer à la fois les tables et les procédures stockées au même type d'entité. Vous ne voulez pas vraiment que le client doive faire la distinction entre les deux mappages.
  • Sur une note connexe, il est difficile d'écrire des règles métier et un code d'entité complets et efficaces. En effet, que ce soit ou non une bonne idée est discutable.

D'autre part, une fois que vous avez un ObjectContext, la mise en œuvre du modèle référentiel est trivial. En effet, pour les cas qui ne sont pas particulièrement complexes, le Repository est une sorte de wrapper autour des types ObjectContext et Entity.

+2

Merci Craig. Je suis tombé sur du code dans un blog de Simon Segal à http://www.simonsegal.net/blog/2009/01/13/entity-framework-repository-specifications-and-fetching-strategies/ qui fournit quelques exemples d'implémentation de Repository pour Entity Framework. – Weej

+0

Utilisez-vous actuellement EntityFramework dans vos conceptions? Y a-t-il des difficultés dans la mise en œuvre? Merci encore – Weej

+0

Oui, nous utilisons Entity Framework. Il n'y a aucune difficulté à implémenter le Repository; est trivial. Nous avons toutes sortes de difficultés avec Entity Framework lui-même; Je pense que c'est probablement vrai pour n'importe quel ORM. –

7

Je dirais que vous devriez regarder le ObjectContext comme UnitOfWork, et non pas comme un dépôt.

Un ObjectContext ne peut pas être un dépôt -imho- car il est « à générique ». Vous devez créer vos propres référentiels, qui ont des méthodes spécialisées (comme GetCustomersWithGoldStatus par exemple) à côté des méthodes CRUD habituelles.

Alors, ce que je ferais, est de créer des dépôts (un pour chaque racine globale), et que ces dépôts utilisent ObjectContext.

+0

Merci pour les commentaires Frederik. Implémenteriez-vous GetCustomersWithGoldStatus directement dans le référentiel? Avez-vous envisagé d'utiliser des méthodes d'extension? Pensez-vous que les méthodes d'extension ont leur place dans ce scénario? – Weej

+0

Sur quel type créeriez-vous une telle méthode d'extension? Je le créerais en effet sur le référentiel, mais pas en tant que méthode d'extension. Le référentiel peut être considéré comme 'la collection' d'où proviennent les entités, donc je pense que c'est un endroit valide pour le faire de cette manière –

0

J'aime avoir une couche référentiel pour les raisons suivantes:

EF

de Gotcha

Quand vous regardez certains des tutoriels en cours sur EF (Code première version), il est évident qu'il ya un nombre de gotcha à traiter, notamment autour des graphes d'objets (entités contenant des entités) et des scénarios déconnectés. Je pense qu'un calque de référentiel est idéal pour les placer au même endroit.

Une image claire des mécanismes d'accès aux données

Un référentiel donne une image spécifique à la façon dont la BL accède et mettre à jour la banque de données. Il expose des méthodes qui ont un but unique clair, et peuvent être testées indépendamment du BL. Exemple standard à partir des manuels, Find() pour rechercher une entité unique. Un exemple plus spécifique à l'application, Clear() pour effacer une table db.

Une place pour les optimisations

Inévitablement vous heurtez problèmes de performances lors de l'utilisation EF vanille. J'utilise le référentiel pour masquer les mécanismes d'optimisation du BL.

Exemples,

GetKeys() pour projeter les clés mises en cache des tables (pour les décisions Insertion/Mise à jour). La lecture de la clé seulement est plus rapide et utilise moins de mémoire que la lecture de l'entité complète.

Chargement en masse via SqlBulkCopy. EF sera inséré par des instructions SQL individuelles. Si vous voulez qu'une seule instruction insère plusieurs lignes, SqlBulkCopy est un bon mécanisme. Le référentiel encapsule ceci et fournit des métadonnées pour SqlBulkCopy. En plus de la méthode Insert, vous avez besoin d'une méthode StartBatch() et EndBatch(), qui est également un argument pour une couche UnitOfWork.