87 votes

Réduire les référentiels pour agréger les racines

J'ai actuellement un référentiel pour à peu près chaque table dans la base de données et souhaiterait s'aligner davantage sur moi-même avec DDD par leur réduction à l'agrégation des racines.

Supposons que j'ai les tableaux suivants, User et Phone. Chaque utilisateur peut avoir un ou plusieurs téléphones. Sans la notion de racine d'agrégat je pourrais faire quelque chose comme ceci:

//assuming I have the userId in session for example and I want to update a phone number
List<Phone> phones = PhoneRepository.GetPhoneNumberByUserId(userId);
phones[0].Number = "911";
PhoneRepository.Update(phones[0]);

Le concept de l'ensemble des racines est plus facile à comprendre sur le papier que dans la pratique. Je n'aurai jamais les numéros de téléphone qui n'appartiennent pas à un Utilisateur, de sorte qu'il est logique d'en finir avec la PhoneRepository et incorporer téléphone méthodes liées à la UserRepository? En supposant que la réponse est oui, je vais réécrire le code précédent de l'échantillon.

Suis-je autorisé à avoir une méthode sur la UserRepository qui renvoie les numéros de téléphone? Ou faut-il toujours retourner une référence à un Utilisateur, puis traverser la relation par l'Utilisateur pour obtenir les numéros de téléphone:

List<Phone> phones = UserRepository.GetPhoneNumbers(userId);
// Or
User user = UserRepository.GetUserWithPhoneNumbers(userId); //this method will join to Phone

Indépendamment de la façon dont je acquérir les téléphones, en supposant que j'ai modifié l'un d'eux, comment puis-je mettre à jour? Ma compréhension est que les objets en vertu de la racine doit être mis à jour par le biais de la racine, ce qui me permettrait d'orienter vers le choix #1 ci-dessous. Bien que cela fonctionne parfaitement bien avec Entity Framework, cela semble extrêmement onu-descriptif, parce que la lecture du code, je n'ai aucune idée de ce que je suis réellement mise à jour, même si Entity Framework est de garder sur l'onglet objets modifiés dans le graphique.

UserRepository.Update(user);
// Or
UserRepository.UpdatePhone(phone);

Enfin, en supposant que j'ai plusieurs tables de recherche qui ne sont pas vraiment liée à quoi que ce soit, tels que l' CountryCodes, ColorsCodes, SomethingElseCodes. Je pourrais les utiliser pour remplir des listes déroulantes ou pour toute autre raison. Êtes autonome de ces référentiels? Peuvent-ils être combinés dans une sorte de logique de regroupement/référentiel tel que CodesRepository? Ou est-ce avec les meilleures pratiques.

12voto

amit_g Points 15415

Vous pouvez utiliser n'importe quelle méthode que vous voulez dans votre référentiel :) Dans les deux cas que vous citez, il est logique de retour à l'utilisateur la liste de téléphone renseigné. Normalement, l'utilisateur de l'objet ne serait pas entièrement rempli avec tous les sous de l'information (disons toutes les adresses, numéros de téléphone) et on peut avoir différentes méthodes pour obtenir l'objet utilisateur remplie avec différents types d'informations. Cette fonction est appelée au chargement différé.

User GetUserDetailsWithPhones()
{
    // Populate User along with Phones
}

Pour la mise à jour, dans ce cas, l'utilisateur est en train d'être mis à jour, pas le numéro de téléphone lui-même. Le modèle de stockage peut stocker le téléphone d'une autre table, et de cette façon vous pouvez penser que seulement les téléphones sont en cours de mise à jour mais ce n'est pas le cas si vous pensez que de DDD point de vue. Autant que la lisibilité est concerné, alors que la ligne

UserRepository.Update(user)

seul à ne pas transmettre ce qui est en train d'être mis à jour, le code ci-dessus, il serait de rendre clair ce qui est mis à jour. Aussi, il serait le plus susceptible d'être une partie d'une extrémité avant d'un appel de méthode qui peut signifiy ce qui est mis à jour.

Pour les tables de recherche, et en fait même le contraire, il est utile d'avoir GenericRepository et l'utiliser. Le dépôt personnalisée peut hériter de la GenericRepository.

public class UserRepository : GenericRepository<User>
{
    IEnumerable<User> GetUserByCustomCriteria()
    {
    }

    User GetUserDetailsWithPhones()
    {
        // Populate User along with Phones
    }

    User GetUserDetailsWithAllSubInfo()
    {
        // Populate User along with all sub information e.g. phones, addresses etc.
    }
}

Recherche pour Générique Référentiel Entity Framework et vous fine beaucoup de belles mise en œuvre. Utiliser l'un de ces ou écrire votre propre.

10voto

Darren Lewis Points 5139

Votre exemple sur l'ensemble de la Racine du référentiel est parfaitement bien je.e toute entité qui ne peut exister sans dépendre de l'autre ne devrait pas avoir son propre référentiel (dans votre cas de Téléphone). Sans cette considération, vous pouvez rapidement vous retrouver avec une explosion des Dépôts dans un mappage 1-1 db tables.

Vous devriez regarder à l'aide de l'Unité de Travail modèle pour les modifications de données plutôt que de les dépôts eux-mêmes, comme je le pense de vous causer une certaine confusion autour de l'intention quand il s'agit de la persistance des modifications dans la db. Dans un EF solution à l'Unité de Travail est essentiellement une interface wrapper autour de votre Contexte EF.

En ce qui concerne votre référentiel pour les données de recherche il suffit de créer une ReferenceDataRepository qui devient responsable pour les données qui ne sont pas spécifiquement appartiennent à une entité de domaine (Pays, Couleurs, etc).

5voto

Arnis L. Points 18316

Si le téléphone n'a pas de sens w/o de l'utilisateur, c'est une entité (si vous Vous souciez de leur identité) ou de la valeur de l'objet et doit toujours être modifiées par l'utilisateur et de l'extrait/mis à jour ensemble.

Pensez à agréger des racines dans le contexte de la definers - ils tirer des contextes locaux, mais sont dans un contexte global (Votre demande) eux-mêmes.

Si Vous suivez domain driven design, les dépôts sont censés être de 1:1 par agrégat racines.
Pas d'excuses.

Je parie que ce sont des problèmes auxquels Vous êtes confrontés:

  • difficultés techniques de la relation d'objet d'adaptation d'impédance. Vous êtes aux prises avec la persistance ensemble de graphes d'objets avec facilité et entity framework genre un ne parvient pas à aider.
  • modèle de domaine est centré sur les données (par opposition à un comportement centré sur l'). à cause de cela - Vous perdre connaissance au sujet de l'objet de la hiérarchie (mentionné précédemment contextes) et comme par magie, tout devient un agrégat de la racine.

Je ne suis pas sûr de la façon de corriger problème en premier, mais j'ai remarqué que la fixation deuxième on fixe d'abord assez bon. Pour comprendre ce que je veux dire avec un comportement centré sur l', de donner à ce livre un essai.

P. s. La réduction de référentiel pour l'agrégation de la racine n'a pas de sens.
P. p.s. Évitez "CodeRepositories". Qui conduit à des données centrées -> code de procédure.
P. p.p.s Évitez motif d'unité de travail. Agréger les racines doivent définir les limites de transaction.

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