39 votes

ASP.NET MVC - Entités de base de données ou ViewModels?

Je travaille actuellement sur un projet ASP.NET MVC.

Certains développeurs de l'équipe souhaitent lier les entités de base de données générées automatiquement directement aux vues.

D'autres développeurs souhaitent créer des ViewModels personnalisés et les lier aux vues.

Objectivement, quels sont les avantages et les inconvénients des deux approches?

(Par "entités de base de données", je fais référence aux classes générées automatiquement générées par une structure ORM, telles que LINQ to SQL, Entity Framework ou LLBLGen).

50voto

HackedByChinese Points 18294

Certainement utiliser des modèles de vue dans vos vues, et d'utiliser quelque chose comme AutoMapper pour créer des modèles de vue à partir d'entités facilement.

Inconvénients:

  1. Parfois, il se sent comme vous êtes la duplication de code, en particulier, lorsque le modèle de vue et de l'entité ont exactement les mêmes propriétés

Pour:

  1. Vous avez souvent besoin de représenter un objet dans un format plus simple (souvent appelé aplatissement), mais vous avez besoin de la pleine fidélité sur le côté serveur. Cela vous permet de faire la transition entre les deux sans curage de votre modèle de domaine avec présentation trucs.
  2. Agréger les racines ont souvent beaucoup d'objets de valeur et les autres entités qui ne sont pas pertinents d'un point de vue spécifique, et l'omission dans un modèle de vue rend plus facile de travailler avec.
  3. Votre entités auront beaucoup de deux façon références qui sont sensibles en termes d'une API, mais créer un pur enfer lors de la sérialisation pour JSON, XML, etc. Les modèles de vue permettra d'éliminer ces références circulaires.
  4. Vous pouvez souvent utiliser la même entité, mais de différentes manières pour différents points de vue. En essayant d'équilibrer à la fois des besoins sur un type peut créer un énorme gâchis.

16voto

Rob Kent Points 3133

L'orthodoxie, c'est que vous ne devez jamais utiliser votre base de données brutes entités dans vos vues. Comme toute règle, il est là pour être cassé, si vous savez que votre entités bien et que vous comprenez les conséquences, mais il y a de très bonnes raisons de ne pas briser cette règle, notamment lorsque l'on travaille en équipe et avec du code qui sera maintenue à l'avenir par des personnes qui pourraient ne pas comprendre la règle ou les entités ainsi que vous le faites. Les principales raisons sont:

  1. De l'ORM au chargement différé. Imaginez que votre Client dispose d'un paresseux chargé de la collecte des Ordres. Vous passez à la Clientèle à la Vue et il itère sur les Commandes. Vous obtenez un N*1 sélectionnez sur la table Commandes. Mais cela signifie aussi que votre connexion de base de données doit encore être ouvert dans la Vue. Il s'agit d'un modèle que les gens utilisent Transaction par l'Action " qui dispose de la base de données de contexte dans le Action_Executed événement, qui se produit avant que votre Vue est rendue. Donc, vous pourriez être en train d'essayer d'accéder à la base de données après qu'il a été disposé. Même si vous ne le faisons pas maintenant, quelqu'un dans le futur pourrait décider de mettre en œuvre ce modèle, car il est à la mode.

  2. Les préoccupations de ce Dernier sont différents à la base de données Modèle. Par exemple, vous permet de décorer votre ViewModel des propriétés avec des attributs de validation. Ce sont généralement des différents ou concernent uniquement l'INTERFACE utilisateur de ne pas la db. Si vous liez à votre entités de base de données, vous trouverez toutes ces préoccupations de l'INTERFACE utilisateur polluantes vous DB entités.

  3. Liés à l'2 - les exigences de la ViewModel peut exiger calculés ou les propriétés dérivées. Par exemple, un Nom construit à partir des noms et des prénoms. Ce genre de choses sont les mieux gardés dans le ViewModel.

  4. Vous pouvez unité de test de votre Viewmodel en isolement à partir de la base de données. Viewmodel peut se retrouver contenant beaucoup de logique qui doit être l'unité testée. C'est plus facile à tester si il n'est pas lié à votre base de données (comme avec EF entités).

En général, la création et le maintien d'Viewmodel (même sans AutoMapper) n'est pas un rétroprojecteur et vous trouverez qu'il est un bien meilleur modèle de développement global. Je le recommande pour tout, mais les cas les plus simples (recherche de listes de données statiques, par exemple).

12voto

LukLed Points 18010

Je crois à l'aide de modèles de vue est la seule façon d'aller, donc pas de pros pour les entités ORM:) les modèles de Vue non seulement de fournir des données pour la vue, mais ils ont également définir comment afficher devriez regarder (en définissant des modèles) ou comment il doit valider (par l'ajout d'annotations de données ou la mise en œuvre de IDataErrorInfo).

À l'aide de modèles de vue:

Pour:

  • Afficher les modèles contiennent uniquement les propriétés requises par la vue, rien d'autre.
  • Afficher les modèles peuvent contenir certaines règles de validation à l'aide de données d'annotations ou de IDataErrorInfo.
  • Les modèles de vue peut combiner les valeurs de différentes entités de base de données.
  • Afficher les modèles de documents eux-mêmes et ne sont pas liées à un cadre.
  • Les modèles de vue de vous protéger à l'aide de fausses Postes, contenant des valeurs, qui n'ont pas été fournies dans le formulaire, mais ont été contenues dans les entités ORM.
  • Vous pouvez spécifier facilement des modèles d'affichage pour afficher les modèles et les réutiliser dans de nombreux endroits à l'aide de DisplayFor ou EditorFor des aides.

À l'aide de l'ORM entités:

Inconvénients:

  • ORM entités contiennent déjà des données d'annotations, qui peuvent gâcher votre validation. Exemple: champ de Mot de passe de l'utilisateur peuvent être marquées comme Required, mais il n'est pas nécessaire lorsque vous changez de base uniquement les infos de l'utilisateur.
  • ORM entités sont étroitement liées à la Structure (Entity Framework) et peut être pas facile à mettre en œuvre des règles.
  • ORM entités peuvent contenir des propriétés de plus d'un point de vue, mais il est difficile de séparer les règles de validation pour les différents points de vue.
  • En utilisant des entités ORM chargement paresseux peut vous conduire à l'exécution de requêtes SQL lorsque les vues sont rendus. Il ne devrait pas arriver.
  • À l'aide de l'ORM entités peuvent conduire à l'utilisation d'énormes requêtes SQL plutôt que sur les petits. Lorsque vous souhaitez afficher une liste déroulante avec les prénom et nom de famille, vous devez récupérer uniquement le prénom et nom de la base de données, et non l'ensemble des entités.

8voto

Alex York Points 2668

Merci pour les réponses jusqu'à présent ils ont été d'une grande aide dans la compréhension des avantages/inconvénients des deux approches. J'ai une chose à ajouter que personne ne l'a mentionné.

Plus-affichage d'attaque

Préoccupante, l'inconvénient de se liant directement à l'encontre de DB entités est un "sur-affichage d'attaque". C'est là que l'attaquant, à l'aide d'un outil pas plus avancé que FireBug, pouvez insérer des champs de formulaire ne sont pas destinés à être modifiable par l'utilisateur, mais qui n'existe pas sur la DB de l'entité.

Envisager une "Modifier mon profil" de la page. Votre point de vue pourrait ressembler à ceci:

@using(Html.BeginForm() {
  <div>
    @Html.LabelFor(x=> x.FirstName)
    @Html.TextBoxFor(x=> x.FirstName)
  </div>
  <div>
    @Html.LabelFor(x=> x.LastName)
    @Html.TextBoxFor(x=> x.LastName)
  </div>

  <input type="Submit" value="Save" />
}

Elle rendrait le code HTML suivant:

<form action="/profile/edit" method="post">
  <div>
    <label for="FirstName">FirstName</label>
    <input type="text" name="FirstName" value="" />
  </div>
  <div>
    <label for="LastName">LastName</label>
    <input type="text" name="LastName" value="" />
  </div>

  <input type="Submit" value="Save" />
</form>

À l'aide de FireBug, un attaquant doit simplement insérer un morceau de code HTML à l'intérieur de la forme:

  <input type="hidden" name="IsAdmin" value="true" />

...et soudain, les utilisateurs sont en mesure de modifier les données de très inattendu et de manière nuisible.

Voici quelques même les plus cachés des champs de formulaire:

  <input type="hidden" name="ShoppingCart.Items[0].Price" value="0.01" />
  <input type="hidden" name="BankAccount.Balance" value="1000000" />
  <input type="hidden" name="User.Administrator.Password" value="hackedPassword" />

Ouch!

Info tirée de: http://hendryluk.wordpress.com/tag/asp-net-mvc/

5voto

gls123 Points 2013

Une fois, j'ai essayé de développer une application qui a utilisé NHibernate entités directement dans ASP.NET les vues. J'ai rencontré beaucoup de problèmes avec le chargement Paresseux et reporté l'exécution SQL exécute directement à partir de la vue plutôt que dans la couche de logique ou même les contrôleurs. Le déplacement d'un viewmodel et à l'aide de automapper a semblé résoudre tous ces problèmes et rendre l'application plus facile à tester, déboguer et à entretenir.

J'ai aussi trouvé que les modèles de vue ont été utiles dans l'exploitation de toutes les données dont j'ai besoin sur une page. Certains développeurs aiment à utiliser la dynamique ViewBag pour cela, mais c'est mauvais pour les tests et le débogage.

En particulier, les modèles de vue, il est facile quand vous avez voulu prendre les entités associées à partir des listes déroulantes.

AutoMapper a été une bouée de sauvetage sur ce projet, comme il a sauvé d'avoir à écrire une tonne de mappage de code, tout ce que j'avais à faire était de créer la vue modèles et les contrôleurs de automapped à partir d'entités d'afficher des modèles.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X