DTO conventions de nommage, modélisation et héritage

nous construisons une application web en utilisant AngularJS, C# , ASP.Net API Web et NHibernate Fluent. Nous avons décidé d'utiliser DTOs pour transférer des données à la couche de présentation ( vues angulaires). J'avais quelques doutes quant à la structuration générale et à la dénomination des Dto. Voici un exemple pour illustrer mon scénario. Disons que j'ai une entité de domaine appelée client qui ressemble à:

public class Customer
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual Address Address { get; set; }
        public virtual ICollection<Account> Accounts { get; set; }
    }

maintenant, dans ma couche de vues/présentation j'ai besoin de récupérer différentes saveurs de Comme un client:

1) juste Id et nom 2) l'identification , le Nom et l'Adresse 3) Id, Nom, Adresse et comptes

j'ai créé un ensemble de DTOs pour accomplir ceci:

public class CustomerEntry
{
    public  int Id { get; set; }
    public  string Name { get; set; }
}

public class CustomerWithAddress : CustomerEntry
{
    public AddressDetails Address { get; set; }
}

public class CustomerWithAddressAndAccounts : CustomerWithAddress
{
    public ICollection<AccountDetails> Accounts { get; set; }
}

AddressDetails et AccountDetails sont des Dto qui possèdent toutes les propriétés de leurs entités de domaine correspondantes.

cela fonctionne très bien pour les requêtes et les extractions de données ; la question Est de savoir ce que je dois utiliser pour les inserts et les mises à jour. Lors de la création d'un nouveau dossier client , le nom et l'adresse sont obligatoires et les comptes sont optionnels.donc, en d'autres termes, j'ai besoin d'un objet avec toutes les propriétés du client. D'où la confusion:

1) Qu'est-ce que j'utilise pour insérer et mettre à jour? Le client avec L'adresse et les comptes DTO a tout en elle, mais son nom semble un peu maladroit pour être utilisé pour insérer/mises à jour.

2) est-ce que je crée un autre DTO .. si je le fais , ce ne serait pas une duplication comme le nouveau DTO va être exactement comme CustomerWithAddressAndAccounts ?

3) Enfin et surtout , la structure d'héritage DTO décrite ci-dessus semble-t-elle bien adaptée à cette exigence ? Existe-il d'autres façons de modèle ?

j'ai parcouru d'autres Billets sur ce sujet mais je n'ai pas pu faire beaucoup de progrès. Une chose que j'ai fait ramasser était d'éviter d'utiliser le suffixe "DTO" dans les noms de classe. Je pense qu'il se sent un peu superflu.

serait aimer entendre vos pensées

Merci

28
demandé sur Sennin 2013-09-16 22:12:32

3 réponses

recommandation est que vous devriez juste avoir une classe DTO pour chaque entité suffixé avec DTO par exemple CustomerEntryDTO pour le Customer entity (mais vous pouvez certainement utiliser les hiérarchies d'héritage selon le choix et les exigences).

en outre, ajouter un résumé DTOBase type de classe de base ou une interface; et ne pas utiliser des héritages aussi profonds pour chaque adresse, Compte et autre biens à inclure dans les DTO pour enfants. Inclure plutôt ces propriétés dans la même classe CustomerEntryDTO (si possible) comme suit:

[Serializable]
public class CustomerEntryDTO : DTOBase, IAddressDetails, IAccountDetails
{
    public  int Id { get; set; }
    public  string Name { get; set; }
    public AddressDetails Address { get; set; } //Can remain null for some Customers
    public ICollection<AccountDetails> Accounts { get; set; } //Can remain null for some Customemer
}

de plus, vos Dto devraient être sérialisables pour passer au-delà des limites du processus.

pour plus sur le dessin DTO, voir ci-dessous les articles:

Objet De Transfert De Données

MSDN

Edit: Dans le cas où vous ne voulez pas envoyer certaines propriétés sur le fil (je sais que vous en auriez besoin sous condition donc vous devriez explorer plus sur ce point), vous pouvez les exclure du mécanisme de sérialisation en utilisant des attributs tels que NonSerialized (mais il ne fonctionne que sur les champs et non sur les propriétés, voir l'article de contournement pour utiliser avec les propriétés: non sérialisé sur propriété ). Vous pouvez également créer votre propre attribut personnalisé tel que ExcludeFromSerializationAttribute et l'appliquer aux propriétés que vous ne voulez pas envoyer chaque fois sur le fil basé sur certaines règles/conditions. voir Aussi: Conditionnel sérialisation xml

Edit 2: Utilisez des interfaces pour séparer les différentes propriétés de la classe CustomerEntryDTO . Voir L'Interface Principe de ségrégation sur Google ou MSDN. Je vais essayer de mettre un échantillon explication plus tard.

10
répondu VS1 2017-05-23 11:54:43

Qu'est-ce que j'utilise pour insérer et mettre à jour?

  1. les opérations de services sont généralement définies en relation très étroite avec les opérations commerciales. Le langage des affaires ne parle pas en termes d '" encarts "et de" mises à jour", pas plus que les services.

  2. service de gestion de la clientèle est susceptible d'avoir une certaine Register opération qui prend le nom du client et peut-être un autre les paramètres facultatifs.

est-ce que je crée une autre DTO?

Oui, vous devriez créer un autre DTO.

parfois, un contrat d'exploitation de service peut suffire et il n'est pas nécessaire de définir une DTO distincte pour une opération particulière:

function Register(UserName as String, Address as Maybe(of String)) as Response

mais la plupart du temps il est préférable de définir une classe DTO séparée, même pour une seule opération de service:

class RegisterCommand
    public UserName as String
    public Address as Maybe(of String)
end class

function Register(Command as RegisterCommand) as Response

RegisterCommand DTO peut sembler très similaire à CustomerWithAddress DTO parce qu'il a les mêmes domaines, mais en fait ces 2 Dto ont des significations très différentes et ne se remplacent pas.

par exemple, CustomerWithAddress contient AddressDetails , tandis qu'une simple représentation d'adresse String peut suffire pour enregistrer un client.

L'utilisation d'un DTO séparé pour chaque opération de service prend plus de temps à écrire mais plus facile à maintenir.

1
répondu Lightman 2016-01-04 13:42:12

à partir de votre item 1, pour les inserts et mises à jour, il est préférable d'utiliser le modèle de commande. Selon CQRS, vous n'avez pas besoin de DTOs. Considérez ce schéma: CQRS — basic patterns via blogs.msdn.com

-1
répondu Vitaly Chirkov 2014-09-10 19:22:05