7
votes

Modèle de référentiel et types de retour

J'utilise le motif de référentiel où j'ai une classe de référentiel par table de base de données. Je me demandais comment vous vous demandez comment vous approchez des questions qui n'ont besoin que de renvoyer un nombre spécifique de colonnes

par exemple, disons que j'ai le suivant

Table d'article (table de fiction) xxx

dans mon code je crée un objet avec les champs ci-dessus appelé élément.cs (actuellement pas à l'aide d'un orm).

Si j'ai plusieurs scénarios où je besoin de revenir

  1. itemID
  2. une combinaison d'achat et de nom
  3. itemID et prix

    qui serait la meilleure approche?

    1. Obtenez tous les champs de la table d'articles et renvoyez un objet d'élément (1 requête de repo)
    2. Créez trois requêtes dans Repo et renvoyez un objet d'élément pour chacun
    3. Créez trois requêtes dans Repo et renvoyez seulement ce qui est nécessaire?

      Imaginez maintenant ce scénario avec une table avec plus de 10 champs.

      Personnellement, j'aime l'option une, mais je ne suis pas sûr s'il y a un meilleur moyen d'y aller.


0 commentaires

5 Réponses :


7
votes

J'utilise personnellement un référentiel de type générique et j'ai mon lecture asqueriserable () code>

voici l'interface. p>

public class PersonsService
{
    private PersonRepository<Person> personRepository;

    public PersonService()
    {
        personRepository = new PersonRepository<Person>();
    }

    public UsablePerson GetPersonByID(int ID)
    {
        UsablePerson person = (from p in personRepository<Person>.Retrieve
                               where p.ID = ID
                               select new UsablePerson { p.FirstName, 
                                                         p.LastName, 
                                                         p.EmailAddress }).FirstOrDefault();

        return person;
    }
}


12 commentaires

Juste pour voir si je suis sur la même page. Pour des requêtes plus spécifiques telles que (getpersonbyID), vous retournez l'enregistrement de la personne entière du repo, puis dans la couche de service entrant toutes les informations inutiles et renvoyez simplement l'identifiant? Pourriez-vous montrer un exemple de cela, car c'est ce que je passe beaucoup de temps avec. Je ne sais pas si je devrais créer beaucoup de méthode de repo ou en avoir un qui retourne toujours toutes les colonnes de table (c'est-à-dire une ligne entière)


J'ai essayé de mon mieux de mémoire ... Je n'ai pas mon IDE devant moi, donc il y a probablement quelques erreurs dans l'exemple ci-dessus. Espérons que vous obtenez la photo.


J'aime cette technique car elle réduit le nombre de méthodes dans les référentiels. Mais, j'ai toujours appris que vous ne devriez retourner que les colonnes dont vous avez besoin d'une base de données, il semble qu'avec un référentiel, vous retournez toujours une collection d'entités ou d'entité. Est-ce l'intention du motif de référentiel? Peut-être que je suis en train de penser à l'impact de la performance de la base de données


Étant donné que le référentiel récupération est requis, vous pouvez faire exactement ce dont vous avez besoin ... Laissez-moi faire une mise à jour rapide ....


essayez mon dernier édition ... encore une fois, aucun IDE, donc j'aurais pu manquer quelque chose de mineur :-p


Votre exemple semble bon envers moi :) Je suppose juste un rapide oui ou non à cette question. Dans la couche de référentiel, il est recommandé de toujours renvoyer une collection de type entité ou d'entité, puis de filtrer dans la couche de service?


C'est ma préférence à coup sûr. LINQ to SQL retarde l'exécution aussi longtemps que possible, alors interrogez-le à la couche de service empêchant le représentant d'interroger des éléments dont vous n'avez pas besoin. Ce n'est pas seulement que vous appelez quelque chose comme firstordfault () , unique () , tolist () , etc., que l'appel à la base de données passe réellement .


Oh ... ça fonctionne vraiment bien avec Linq à SQL, mais je n'utilise pas de mappeuse ORM. Je vais probablement finir par utiliser cette technique cependant


Nitpick: Vous devez utiliser l'injection de constructeur pour votre contexte de données si vous souhaitez effectuer des tests unitaires. Chaque fois que vous avez neuf sur une dépendance qui ne fait pas partie de la BCL, vous rendez votre code plus simple.


Il incombe au référentiel d'interroger et de renvoyer les objets de domaine. Vous venez de passer la responsabilité de la requête dans un service pour interroger les données - pas une bonne idée. Soudainement, quelque chose à faire changer ce qui se fait interroger dans votre base de données et la séparation des préoccupations n'existe plus. Où testez-vous vos questions? Des référentiels et des services et potentiellement d'autres parties de votre application si vous continuez de retourner la pile. Ensuite, la responsabilité des requêtes d'écriture n'est plus bien définie dans les référentiels.


@Bomboca Ma raison de l'abstraction avec un irpostage est parce que je construis des applications multiples multiples. Par conséquent, j'ai une implémentation de serveur (utilisant SQL Server && EntityFramework / Nhibernate et al) et j'ai une implémentation de téléphonie mobile (à l'aide de SQLite). Ensuite, j'injecte le référentiel en fonction duquel le bit est enregistré dans le conteneur DI. C'est une couche d'abstraction simple avec un but.


@Chaseflorell Je comprends que vous avez une raison qui est très apparente dans votre réponse. Et je suis sûr que vos affaires continueront de travailler des merveilles, mais vous n'avez pas discuté de ma déclaration indiquant que la responsabilité de la requête n'est plus bien définie dans votre référentiel. Je serai heureux que au moins vous avez envisagé le pros / inconvénient de vos décisions et si la prestation est supérieure à celle du bas, alors alors soyez-le. Bonne chance :)



0
votes

J'aime les référentiels de Linq pour ce genre de chose. LINQ2SQL, MSEF ou LINQ2NH vous permettrait, via la méthode Select (), de définir votre liste de colonnes. Vous recevriez ensuite un objet de domaine ou une classe d'entité peuplée avec seulement ce que vous avez spécifié. Vous pouvez avoir un code supplémentaire pour mapper cela dans une DTO ou simplement utiliser la classe de domaine sachant que ce n'était pas complètement "hydraté".


0 commentaires

2
votes

Si vous pensez à la conception basée sur le domaine, le fait qu'un seul objet a une configuration différente indique très probablement des domaines différents. Cela ne nécessite pas un objet différent pour chacun, mais c'est un bon modèle. Une façon d'y parvenir est d'une classe de base avec l'ensemble minimaliste de propriétés. Vous créez ensuite plus de classes «spécifiques à un domaine» qui héritent de la base.

En ce qui concerne le retour des données, il existe une variété de façons de «trafic sur la circulation» du flux. Plusieurs référentiels séparent joliment les domaines, par exemple. Mais cela ajoute une complexité (pas une bonne idée à moins que ce soit absolument nécessaire). Je n'aime pas un seul référentiel qui retourne des objets différents. Il est plus acceptable si vous avez des propriétés nullables (peut-être).

Je n'aime pas Linq à SQL comme DAL, car @Kethis l'a suggéré, mais je travaille dans un environnement d'entreprise et Linq à SQL est essentiellement à l'échelle. Utiliser LINQ Sinon, c'est génial. Juste mes deux cents.

Si vous pouvez retourner un type d'objet, c'est mieux. Si la différence entre les objets est basée sur des autorisations, envisagez de supprimer les données que l'utilisateur ne doit pas voir. Remarque Cependant, ce n'est pas aussi évolutif si vous saisissez un grand nombre d'objets.


1 commentaires

J'ai tendance à renvoyer seulement un type d'objet du repo, mais ce qui me trébuche est de devoir retourner un objet d'entité? Par exemple, si j'ai une méthode appelée getemployeeid, dois-je retourner un objet employé avec ce champ? Ou devrais-je retourner juste un numéro d'employé? Devrais-je simplement utiliser une méthode getemplelployee ou devrais-je les casser dans des méthodes plus spécifiques dans le repo comme Getemployeeid vs toujours en utilisant GetEnployee?



9
votes

i Ajoutez des méthodes à mes référentiels lorsque j'en ai besoin de contrairement aux référentiels génériques où vous obtenez un ensemble de méthodes, peu importe si vous en avez besoin ou non.

retour iquéryable est une abstraction fuite.

Regardez un coup d'œil au design dirigé sur le domaine (le livre) et vous aurez une bonne idée de la façon dont les référentiels bien conçus doivent ressembler.

J'ai aussi écrit un rant sur les référentiels génériques: http://blog.gauuffin.org/2012/02/generic-repositories-a-silly-abstraction-layer/


1 commentaires

D'accord, retourner un iquéryable fait tout le contraire de ce que vous voulez qu'un référentiel fasse - il s'agit simplement d'une préoccupation infrastructurelle de retour dans votre couche de domaine.



1
votes

Pourquoi retourneriez-vous tous les champs lorsque vous n'avez réellement besoin que de quelques-uns d'entre eux? Sélectionnez les champs que vous souhaitez vraiment si vous êtes inquiet pour la performance. Je ne suis pas un grand fan de Strictement à la suite d'un modèle de conception, vous devriez peut-être envisager de modifier la conception en fonction de votre exigence.


0 commentaires