web-dev-qa-db-fra.com

Pourquoi utiliser le modèle de référentiel ou s'il vous plaît l'expliquez-moi?

J'apprends le modèle de référentiel et lisais Modèle de référentiel avec Entity Framework 4.1 et Code First et Modèle de référentiel générique - Entity Framework, ASP.NET MVC et Triangle de test unitaire sur la manière dont ils implémentent le modèle de référentiel avec Entity Framework.

En disant 

• Masquer EF de la couche supérieure
• Rendre le code mieux testable

Je comprends bien le code, mais pourquoi cacher le EF de la couche supérieure?

En regardant leur implémentation, il semble simplement envelopper le framework d’entité avec une méthode générique pour interroger le framework d’entité. En fait, quelle est la raison de cela?

Je suppose que c'est pour 

  1. Couplage lâche (c'est pourquoi cacher EF de la couche supérieure?) 
  2. Évitez de répéter la même instruction LINQ pour une même requête

Est-ce que je comprends bien? 

Si j'écris un DataAccessLayer qui est une classe ont des méthodes

QueryFooObject(int id)
{
..//query foo from entity framework
} 

AddFooObject(Foo obj)
{
.. //add foo to entity framework
}
......
QueryBarObject(int id)
{
..
}

AddBarObject(Bar obj)
{
...
}

Est-ce aussi un motif de référentiel?

Explication pour mannequin sera génial :)

47
King Chan

Une chose est d'augmenter la testabilité et d'avoir un couplage lâche avec la technologie de persistance sous-jacente. Mais vous aurez également un référentiel par objet racine agrégé (par exemple, un ordre peut être une racine agrégée, qui comporte également des lignes de commande (qui ne sont pas la racine agrégée), pour rendre la persistance des objets de domaine plus générique.

Cela facilite également la gestion des objets, car lorsque vous enregistrez une commande, vos éléments enfants (qui peuvent être des lignes de commande) seront également sauvegardés.

7
Espen Burud

Je ne pense pas que tu devrais.

Entity Framework est déjà une couche d'abstraction sur votre base de données. Le contexte utilise le modèle d'unité de travail et chaque DBSet est un référentiel. L'ajout d'un modèle de référentiel au-dessus vous sépare des fonctionnalités de votre ORM.

J'en ai parlé dans mon billet de blog: http://www.nogginbox.co.uk/blog/do-we-need-the-repository-pattern

La principale raison pour laquelle vous avez ajouté votre propre implémentation de référentiel est que vous pouvez utiliser l'injection de dépendances et rendre votre code plus testable.

EF n’est pas très testable au départ, mais il est assez facile de créer une version modifiable du contexte de données EF avec une interface pouvant être injectée.

J'en ai parlé ici: http://www.nogginbox.co.uk/blog/mocking-entity-framework-data-context

Si nous n'avons pas besoin du modèle de référentiel pour rendre EF testable, je ne pense pas que nous en ayons besoin du tout.

59
Richard Garside

Cette image facilite la compréhension

 enter image description here

5
Sanjeewa

C'est aussi un avantage de garder vos requêtes dans un endroit central; sinon, vos questions sont dispersées et sont plus difficiles à gérer.

Et le premier point que vous mentionnez: "Cacher EF" est une bonne chose! Par exemple, la sauvegarde de la logique peut être difficile à mettre en œuvre. Plusieurs stratégies s’appliquent le mieux dans différents scénarios. Surtout quand il s'agit de sauver des entités qui ont également des changements dans les entités liées.

L'utilisation de référentiels (en combinaison avec UnitOfWork) peut également centraliser cette logique.

Ici sont quelques vidéos avec une explication de Nice.

4
Jowen

Les systèmes de référentiel sont bons pour les tests.

L'une des raisons est que vous pouvez utiliser l'injection de dépendance.

En gros, vous créez une interface pour votre référentiel et vous la référencez lorsque vous créez l'objet. Vous pourrez ensuite créer ultérieurement un objet fictif (avec moq par exemple) qui implémentera cette interface. En utilisant quelque chose comme ninject, vous pouvez alors lier le type approprié à cette interface. Boom, vous venez de sortir une dépendance de l'équation et de la remplacer par quelque chose de testable.

L'idée est de pouvoir échanger facilement les implémentations d'objets à des fins de test.

3
Jordan

Je sais qu'il est mauvais de fournir des liens en réponse ici, cependant je voulais partager la vidéo qui explique les différents avantages de Repository Pattern lors de son utilisation avec Entity Framework. Ci-dessous le lien de youtube. 

https://www.youtube.com/watch?v=rtXpYpZdOzM

Il fournit également des détails sur la manière de mettre en œuvre correctement le modèle de référentiel.

0
Rakesh Guranani

Lorsque vous concevez vos classes de référentiel pour qu'elles ressemblent à un objet de domaine, afin de fournir le même contexte de données à tous les référentiels et de faciliter la mise en œuvre de l'unité de travail, le modèle de référentiel est logique. Veuillez trouver ci-dessous quelques exemples artificiels.

  class StudenRepository
  {
     dbcontext ctx;
     StundentRepository(dbcontext ctx)
     {
       this.ctx=ctx;
     }
     public void EnrollCourse(int courseId)
     {
       this.ctx.Students.Add(new Course(){CourseId=courseId});
     }
  }

  class TeacherRepository
  {
     dbcontext ctx;
     TeacherRepository(dbcontext ctx)
     {
       this.ctx=ctx;
     }
     public void EngageCourse(int courseId)
     {
       this.ctx.Teachers.Add(new Course(){CourseId=courseId});
     }
  }

  public class MyunitOfWork
  {
     dbcontext ctx;
     private StudentRepository _studentRepository;
     private TeacherRepository _teacherRepository;

     public MyunitOfWork(dbcontext ctx)
     {
       this.ctx=ctx;
     }

    public StudentRepository StundetRepository
    {
       get
       {       
             if(_studentRepository==null)
                _stundentRepository=new StundetRepository(this.ctx);

            return _stundentRepository;    
       }
    }

    public TeacherRepository TeacherRepository 
    {
       get
       {       
             if(_teacherRepository==null)
                _teacherRepository=new TeacherRepository (this.ctx);

            return _teacherRepository;    
       }
    }

    public void Commit()
    {
         this.ctx.SaveChanges();
    }
  }

//some controller method
public void Register(int courseId)
{
  using(var uw=new MyunitOfWork(new context())
  {
    uw.StudentRepository.EnrollCourse(courseId);
    uw.TeacherRepository.EngageCourse(courseId);
    uw.Commit();
  }
}
0
Mohanraja

La même raison pour laquelle vous ne codez pas en dur les chemins de fichiers dans votre application: couplage lâche et encapsulation . Imaginez une application avec des références codées en dur à "c:\windows\fonts" et aux problèmes que cela peut causer. Vous ne devriez pas coder en dur les références aux chemins, alors pourquoi devriez-vous coder en dur les références à votre couche de persistance? Cachez vos chemins derrière les paramètres de configuration (ou des dossiers spéciaux ou tout ce que votre système d'exploitation supporte) et cachez votre persistance derrière un référentiel. Il sera beaucoup plus facile de tester les unités, de les déployer dans d'autres environnements, d'échanger des implémentations et de raisonner sur vos objets de domaine si les problèmes de persistance sont masqués derrière un référentiel.

0
Trystan Spangler