Une application ASP.NET MVC doit-elle utiliser directement Entity Framework comme modèle?

22

Je crée ma première application MVC dans Visual Studio 2013 (MVC 5) et je ne suis pas certain de la meilleure façon de configurer mon modèle.

J'ai généré un modèle de structure d'entité à l'aide de code-first à partir d'une base de données existante. Mon premier réflexe a été de créer des classes intermédiaires qui seraient le modèle utilisé par les vues et de faire travailler ces classes avec les classes framework d'entité.

Pendant que j'écrivais les classes intermédiaires, j'ai réalisé que je ré-implémentais principalement beaucoup de choses que les classes EF faisaient déjà juste avec le setter privé occasionnel ou cast d'un type de données à un autre. Cela semblait donc être un gaspillage.

La règle générale est-elle d'utiliser directement les classes de structure d'entité comme modèle pour une application MVC? Ou y a-t-il un avantage qui me manque pour la construction de ces classes intermédiaires?

Mike D.
la source
Si vous utilisiez le code en premier, alors il n'y avait pas de base de données existante, non?
Isaac Kleinman
1
Avec EF 6.1+, vous pouvez générer un modèle en premier code à partir d'une base de données existante. Voir cet article MSDN: msdn.microsoft.com/en-au/data/jj200620.aspx
Mike D.

Réponses:

23

Dans mes applications, j'ai toujours séparé les choses, avec différents modèles pour la base de données (Entity Framework) et MVC. Je les ai également séparés en différents projets:

  • Example.Entities - contient mes entités pour EF et le contexte DB pour y accéder.
  • Example.Models - contient des modèles MVC.
  • Example.Web - application web. Dépend à la fois de Example.Domain et de Example.Models.

Au lieu de contenir des références à d'autres objets comme le font les entités de domaine, les modèles MVC contiennent des ID sous forme d'entiers.

Lorsqu'une demande GET pour une page arrive, le contrôleur MVC exécute la requête de base de données, qui renvoie une entité. J'ai écrit des méthodes "Convertisseur" qui prennent une entité de domaine et la convertissent en un modèle MVC. Il existe d'autres méthodes qui font le contraire (d'un modèle MVC à une entité de domaine). Le modèle est ensuite transmis à la vue, et donc au client.

Lorsqu'une demande POST arrive, le contrôleur MVC obtient un modèle MVC. Une méthode de conversion le convertit en une entité de domaine. Cette méthode effectue également toutes les validations qui ne peuvent pas être exprimées en tant qu'attributs et s'assure que si l'entité de domaine existe déjà, nous la mettons à jour plutôt que d'en obtenir une nouvelle. Les méthodes ressemblent généralement à ceci:

public class PersonConverter
{
    public MyDatabaseContext _db;

    public PersonEntity Convert(PersonModel source)
    {
         PersonEntity destination = _db.People.Find(source.ID);

         if(destination == null)
             destination = new PersonEntity();

         destination.Name = source.Name;
         destination.Organisation = _db.Organisations.Find(source.OrganisationID);
         //etc

         return destination;
    }

    public PersonModel Convert(PersonEntity source)
    {
         PersonModel destination = new PersonModel()
         {
             Name = source.Name,
             OrganisationID = source.Organisation.ID,
             //etc
         };

         return destination;
    }
}

En utilisant ces méthodes, je supprime la duplication qui se produirait autrement dans chaque contrôleur. L'utilisation de génériques peut dédupliquer encore plus les choses.

Faire les choses de cette façon présente de multiples avantages:

  • Vous pouvez personnaliser un modèle pour une vue ou une action spécifique. Supposons que vous ayez un formulaire d'inscription pour une personne qui, une fois soumis, crée de nombreuses entités différentes (personne, organisation, adresse). Sans modèles MVC séparés, ce sera très difficile.
  • Si j'ai besoin de transmettre à la vue plus d'informations que celles qui seraient autrement disponibles uniquement dans l'entité, ou de combiner deux entités en un seul modèle, mes précieux modèles de base de données ne sont jamais touchés.
  • Si vous sérialisez un modèle MVC en JSON ou XML, vous obtenez uniquement le modèle immédiat en cours de sérialisation, pas toutes les autres entités liées à celui-ci.
Jack Scott
la source
Bonne réponse, je recommanderais d'utiliser ValueInjector ou quelque chose de similaire (personnellement, je détestais l'automappeur) au lieu de mapper manuellement les propriétés d'une classe à l'autre.
Rocklan
1
Plutôt que d'ajouter une réponse distincte, je vais simplement commenter ici que dans les pratiques DDD, vos "convertisseurs" et modèles séparés pour la vue seraient considérés comme faisant partie de la couche de service d'application. Fondamentalement, il permet à votre modèle de domaine d'être aussi complexe que nécessaire tout en cachant cette complexité à l'application. Il empêche également l'application de devoir être modifiée en raison d'un changement dans le modèle de domaine. L'ASL gère la traduction.
Michael Brown
Vous appelez donc chaque modèle que vous avez dans votre PersonModel (c'est-à-dire l'objet Organisation) pour obtenir les informations de ce modèle? Supposons que vous ayez un formulaire pour mettre à jour la personne et les informations sur l'organisation, auriez-vous un appel supplémentaire lorsque vous mettriez à jour l'organisation? J'utilise des procs stockés, donc ne pourrais-je pas envoyer tous les attributs du modèle et tous les attributs du modèle contenant en même temps?
2015 lumineux
1
Comment géreriez-vous le mappage d'une collection? Cela semble avoir été beaucoup plus compliqué dans EF6 car vous ne pouvez plus simplement créer une nouvelle liste d'entités avec les mises à jour car cela recrée tout simplement ...
Gerard Wilkinson
2
Au lieu d'écrire vos propres classes de convertisseur, je vous recommande d'utiliser la bibliothèque Automapper qui a été écrite pour résoudre ce problème. Il a beaucoup mûri depuis 2014!
BenSmith
6

Je dirais que cela dépend vraiment de votre application. S'agit-il simplement de CRUD pur, sans logique métier? Ensuite, j'utilisais les modèles EF directement dans mes vues.

La plupart du temps, au moins une logique métier est impliquée, puis une couche entre les modèles de données / EF et la vue peut être une bonne idée. Dans ce cas, il peut être approprié de faire "CQRS-lite" (voir ci-dessous) et d'utiliser différents modèles pour entrer et sortir de votre contrôleur. La plupart du temps, les modèles de lecture sont beaucoup plus "gras" que les modèles d'écriture ...

Cependant, si l'application contient beaucoup de logique métier et / ou doit évoluer beaucoup, j'en implémenterais au moins le cœur en utilisant CQRS (Command Query Responsibility Segregation), DDD (Domain Driven Design) et éventuellement Event Sourcing. Ensuite, EF pourrait être utilisé comme façade du modèle de lecture.

Rappelez-vous également que vous n'avez pas besoin de vous en tenir à une stratégie / un modèle pour l'ensemble de l'application, certains domaines peuvent être du CRUD pur et d'autres domaines peuvent contenir beaucoup de logique métier ...

jhdrn
la source