Je me demande comment dois-je regrouper mes référentiels? Comme dans les exemples que j'ai vus sur le mvc asp.net et dans mes livres, ils utilisent essentiellement un référentiel par table de base de données. Mais cela semble être beaucoup de référentiels qui vous obligent à appeler de nombreux référentiels plus tard pour des moqueries et autres.
Donc je suppose que je devrais les regrouper. Cependant, je ne sais pas comment les regrouper.
En ce moment, j'ai créé un référentiel d'enregistrement pour gérer tout mon enregistrement. Cependant, il y a comme 4 tables que je dois mettre à jour et avant j'avais 3 référentiels pour le faire.
Par exemple, l'une des tables est une table de licence. Quand ils s'inscrivent, je regarde leur clé et la vérifie pour voir si elle existe dans la base de données. Maintenant, que se passe-t-il si je dois vérifier cette clé de licence ou quelque chose d'autre de cette table à un autre endroit que l'enregistrement?
Un endroit pourrait être la connexion (vérifiez si la clé n'est pas expirée).
Alors, que ferais-je dans cette situation? Réécrire à nouveau le code (interrompre DRY)? Essayez de regrouper ces 2 dépôts et espérez qu'aucune des méthodes ne sera nécessaire à un autre moment (comme peut-être que je pourrais avoir une méthode qui vérifie si userName est utilisé - peut-être que j'aurai besoin de cela ailleurs).
De plus, si je les fusionne, j'aurais soit besoin de 2 couches de service allant dans le même référentiel car je pense qu'avoir toute la logique pour 2 parties différentes d'un site serait long et je devrais avoir des noms comme ValidateLogin (), ValdiateRegistrationForm () , ValdiateLoginRetrievePassword () et etc.
Ou appeler le référentiel de toute façon et avoir juste un nom bizarre?
Il semble juste difficile de créer un référentiel qui a un nom assez général pour que vous puissiez l'utiliser pour de nombreux endroits de votre application et qui ait toujours du sens et je ne pense pas qu'appeler un autre référentiel dans un référentiel serait une bonne pratique?
Réponses:
Une chose que j'ai mal faite en jouant avec le modèle de référentiel - tout comme vous, je pensais que ce tableau se rapportait au référentiel 1: 1. Lorsque nous appliquons certaines règles de Domain Driven Design, le problème de regroupement des référentiels disparaît souvent.
Le référentiel doit être par racine agrégée et non par table. Cela signifie - si l'entité ne doit pas vivre seule (c'est-à-dire si vous avez un
Registrant
qui participe en particulierRegistration
) - c'est juste une entité, elle n'a pas besoin d'un référentiel, elle doit être mise à jour / créée / récupérée via le référentiel de la racine agrégée. fait parti.Bien sûr - dans de nombreux cas, cette technique de réduction du nombre de référentiels (en fait - c'est plus une technique pour structurer votre modèle de domaine) ne peut pas être appliquée car chaque entité est censée être une racine agrégée (cela dépend fortement de votre domaine, Je ne peux fournir que des suppositions aveugles). Dans votre exemple -
License
semble être une racine agrégée car vous devez être en mesure de les vérifier sans contexte d'Registration
entité.Mais cela ne nous limite pas aux référentiels en cascade (le
Registration
référentiel est autorisé à référencer leLicense
référentiel si nécessaire). Cela ne nous limite pas à référencer leLicense
référentiel (préférable - via IoC) directement à partir de l'Registration
objet.Essayez simplement de ne pas conduire votre conception à des complications liées aux technologies ou à un malentendu. Regrouper les référentiels
ServiceX
simplement parce que vous ne voulez pas construire 2 référentiels n'est pas une bonne idée.Il serait préférable de lui donner un nom propre -
RegistrationService
c'est-à - direMais les services doivent être évités en général - ils sont souvent la cause qui conduit à un modèle de domaine anémique .
EDIT:
commencez à utiliser IoC. Cela soulage vraiment la douleur de l'injection de dépendances.
Au lieu d'écrire:
var registrationService = new RegistrationService(new RegistrationRepository(), new LicenseRepository(), new GodOnlyKnowsWhatElseThatServiceNeeds());
vous pourrez écrire:
var registrationService = IoC.Resolve<IRegistrationService>();
Ps serait préférable d'utiliser ce qu'on appelle le localisateur de services communs, mais ce n'est qu'un exemple.
la source
Une chose que j'ai commencé à faire pour résoudre ce problème est de développer des services qui enveloppent N référentiels. J'espère que vos frameworks DI ou IoC pourront vous faciliter la tâche.
public class ServiceImpl { public ServiceImpl(IRepo1 repo1, IRepo2 repo2...) { } }
Cela a-t-il du sens? De plus, je comprends que parler de services dans ce manoir peut ou non être conforme aux principes DDD, je le fais simplement parce que cela semble fonctionner.
la source
Ce que je fais, c'est que j'ai une classe de base abstraite définie comme suit:
public abstract class ReadOnlyRepository<T,V> { V Find(T lookupKey); } public abstract class InsertRepository<T> { void Add(T entityToSave); } public abstract class UpdateRepository<T,V> { V Update(T entityToUpdate); } public abstract class DeleteRepository<T> { void Delete(T entityToDelete); }
Vous pouvez ensuite dériver votre référentiel de la classe de base abstraite et étendre votre référentiel unique tant que les arguments génériques diffèrent par exemple;
public class RegistrationRepository: ReadOnlyRepository<int, IRegistrationItem>, ReadOnlyRepository<string, IRegistrationItem>
etc....
J'ai besoin des référentiels séparés car nous avons des restrictions sur certains de nos référentiels et cela nous donne une flexibilité maximale. J'espère que cela t'aides.
la source
J'ai ceci comme classe de référentiel et oui, j'étends dans le référentiel table / zone mais je dois quand même parfois casser DRY.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MvcRepository { public class Repository<T> : IRepository<T> where T : class { protected System.Data.Linq.DataContext _dataContextFactory; public IQueryable<T> All() { return GetTable.AsQueryable(); } public IQueryable<T> FindAll(Func<T, bool> exp) { return GetTable.Where<T>(exp).AsQueryable(); } public T Single(Func<T, bool> exp) { return GetTable.Single(exp); } public virtual void MarkForDeletion(T entity) { _dataContextFactory.GetTable<T>().DeleteOnSubmit(entity); } public virtual T CreateInstance() { T entity = Activator.CreateInstance<T>(); GetTable.InsertOnSubmit(entity); return entity; } public void SaveAll() { _dataContextFactory.SubmitChanges(); } public Repository(System.Data.Linq.DataContext dataContextFactory) { _dataContextFactory = dataContextFactory; } public System.Data.Linq.Table<T> GetTable { get { return _dataContextFactory.GetTable<T>(); } } } }
ÉDITER
public class AdminRepository<T> : Repository<T> where T: class { static AdminDataContext dc = new AdminDataContext(System.Configuration.ConfigurationManager.ConnectionStrings["MY_ConnectionString"].ConnectionString); public AdminRepository() : base( dc ) { }
J'ai également un datacontext qui a été créé à l'aide de la classe Linq2SQL.dbml.
Alors maintenant, j'ai un référentiel standard implémentant des appels standard comme All et Find et dans mon AdminRepository j'ai des appels spécifiques.
Ne répond pas à la question de DRY bien que je ne pense pas.
la source
Voici un exemple d'implémentation générique de référentiel utilisant FluentNHibernate. Il est capable de conserver n'importe quelle classe pour laquelle vous avez écrit un mappeur. Il est même capable de générer votre base de données à partir des classes de mappeur.
la source
Le modèle de référentiel est un mauvais modèle de conception. Je travaille avec de nombreux anciens projets .Net et ce modèle provoque généralement des erreurs «Transactions distribuées», «Restauration partielle» et «Pool de connexions épuisé» qui pourraient être évitées. Le problème est que le modèle tente de gérer les connexions et les transactions en interne, mais celles-ci doivent être gérées au niveau de la couche contrôleur. EntityFramework fait également déjà abstraction d'une grande partie de la logique. Je suggérerais d'utiliser le modèle de service à la place pour réutiliser le code partagé.
la source
Je vous suggère de regarder Sharp Architecture . Ils suggèrent d'utiliser un référentiel par entité. Je l'utilise actuellement dans mon projet et je suis très satisfait des résultats.
la source