Dernièrement, j'ai beaucoup entendu parler des DTO et de leur utilité, mais je ne trouve pas un bon exemple d'utilisation dans le contexte ASP.NET.
Disons que j'utilise une architecture à trois niveaux:
Où dois-je convertir l'objet EF Employee en un EmployeeDTO POCO?
Disons que je fais la conversion dans la couche d'accès aux données, mais que se passe-t-il dans le service WCF? Doit-il ensuite être converti en un autre objet DataMember
et lorsqu'il parviendra à la couche UI (application Web MVC), devrait-il ensuite être converti pour la troisième fois en modèle? Je vous serais reconnaissant si quelqu'un pouvait s'il vous plaît effacer cela pour moi
Dans une situation similaire, j'avais l'habitude de mettre des dto dans Core qui est connu des trois. Vous avez donc
Noyau | ------------ | | | DAL BL PL
Chaque couche peut fonctionner avec Core.Dto.Employee
. Chaque couche expose également Core.Dto.Employee
en externe dans son API. Mais en interne, chaque couche peut transformer/adapter Core.Dto.Employee
, par exemple. vous lisez à partir de la base de données EF.Employee
puis le convertir en Core.Dto.Employee
. La transformation est contenue par la limite de la couche.
Si vous avez plusieurs modèles différents pour représenter la même chose dans les couches, par exemple PL veut PL.Employee
et DAL fonctionne sur EF.Employee
, vous vous retrouverez avec un gâchis.
Votre couche de service expose les DTO. Cela signifie que dans la couche de service, vous définissez les contrats de données comme vous souhaitez qu'ils soient exposés au monde extérieur. Dans la plupart des cas, il s'agit d'entités aplaties qui n'ont pas nécessairement la même structure que vos entités de base de données.
Il est de la responsabilité de votre couche de service d'utiliser la couche métier/données et de construire les DTO que vous exposez au monde extérieur.
Ce que vous utilisez dans votre entreprise et votre couche de données dépend de l'architecture. Vous pourriez avoir un modèle de domaine mappé avec du code en premier. Dans ce cas, la couche de service mappe les entités de domaine aux contrats de données (DTO). Si vous n'avez pas de modèle de domaine (modèle anémique), vous pouvez également mapper la base de données directement sur vos DTO.
Le site ASP.NET MVC consomme le service et mappe les DTO qu'il reçoit pour dédier des modèles de vue qui sont ensuite passés à la vue spécifique.
En outre, vous pouvez également décider de séparer les requêtes des commandes. C'est une bonne approche car les DTO que vous récupérez en tant que reqult d'une requête sont totalement différents des commandes que vous envoyez au service. Une commande contient uniquement ce qui est nécessaire pour exécuter la commande et contient l'intention de l'entreprise ce que vous voulez réaliser, tandis qu'une requête renvoie un modèle aplati de ce dont vous avez besoin dans l'interface utilisateur.
D'autres remarques:
Jetez un œil à https://stackoverflow.com/a/6310507/1771365 ajouté ici car je n'ai pas assez de réputation pour ajouter des commentaires.
Personnellement, je passerais des entités entre votre couche Persistance et votre couche métier. Lorsque vous utilisez MVC, vous allez probablement passer des modèles de vue à vos contrôleurs. À ce stade, je mapperais votre modèle de vue à vos DTO.
Si vous envisagez d'utiliser DTO entre toutes vos couches, créez un projet transversal que vous pourrez ensuite référencer.
Une approche que j'aime particulièrement est la conversion DTO dans votre couche métier.
Scénario: Votre couche de présentation appelle votre couche métier en passant un DTO. Vous faites un peu de logique et de validation, puis convertissez le DTO en une entité et envoyez-le à votre couche d'accès aux données.
c'est-à-dire UI -> Bus. Couche (convertir en entité) -> Couche de données
J'aime cette approche car je pense que la couche de données ne devrait pas avoir de logique de conversion et devrait recevoir et gérer les entités selon les besoins. Une autre raison pour laquelle cela est efficace est que vous pouvez désormais définir des règles métier/une logique de validation spécifiques pendant le processus de conversion avant de les envoyer à la couche de données. Voici un vieux article MSDN , mais contient de grands détails expliquant une approche similaire.
J'utilise un projet nommé Shared à de telles fins, spécifiquement pour partager un objet avec toutes les couches. Quel que soit le nom, il doit être visible par tous les calques.