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
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:
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.
Qu'est-ce que j'utilise pour insérer et mettre à jour?
-
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.
-
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.
à 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: via blogs.msdn.com