Modèle de conception pour la couche d’access aux données

Vous pourriez penser que c’est un devoir, pour cela je suis désolé. J’ai cherché mais je n’ai pas trouvé de réponse adéquate.

Donc ma question est:

J’ai plusieurs classes et chaque classe a une méthode pour enregistrer. J’ai donc créé une classe distincte pour la gestion de la firebase database.

namespace HospitalMgt.Data { public static class DBConnection { public static ssortingng constr = "Data Source=ABD;Initial Catalog=HospitalMgt;User Id=sa;Password=123"; public static SqlConnection con; // public static SqlCommand com; public static SqlConnection OpenConnection() { con= new SqlConnection(constr); con.Open(); return con; } } } 

Cependant, je ne pense pas qu’il soit approprié d’implémenter toutes les classes avec une classe DBConnection.

Ma question :

  1. Quel modèle de conception est adapté pour surmonter ce problème?
  2. Est-ce une bonne pratique de créer DBConnection en tant que classe? (Ou devrait-il s’agir d’une interface)

J’ai trouvé quelques articles sur les couches DA en utilisant la méthode Factory, mais, à ma connaissance, ce motif ne convient pas à ma situation.

Normalement, si je ne peux utiliser aucun framework existant, j’utilise à la fois les modèles Repository et Active.

Pour plus de simplicité, vous pouvez utiliser uniquement le modèle Repository. Je le définis normalement comme ceci:

 // Define a generic repository interface public interface IRepository where E:IEntity>{ void Add(E entity); void AddRange(IEnumerable entities); IEntity Get(Key key); IEnumerable GetRange(IEnumerable keys); IEnumerable GetAll(); // ..., Update, Delete methods } // Create an abstract class that will encapsulate the generic code public abstract class Repository where E:IEntity>:IRepository{ protected Repository(/*parameter you may need to implement the generic methods, like a ConnectionFactory, table name, entity type for casts, etc */){} public override void Insert(IEntity entity){ // do the insert, treat exceptions accordingly and encapsulate them in your own and more concise Exceptions, etc } // ... } // Create the entities classes, one for each table, that will represent a row of that table public class Car: IEntity{/* Properties */} // Create a specific repository for each table // If the table have a composed key, just create a class representing it public CarRepository: Repository{ public CarRepository(){/* pass the base parameters */} // offer here your specific operations to this table entity public IEnumerable GetByOwner(PersonKey ownerKey){ // do stuff } } 

Vous avez maintenant assez d’outils pour manipuler la firebase database, mais si vous le souhaitez, vous pouvez utiliser le modèle Actif. Un exemple simple:

 public class Person:IEntity{ public PersonKey Key{get;} public IEnumerable OwnedCars{ get{ CarRepository rep = DBSingletons.Cars; return rep.GetByOwner(this.Key); } set{ // do stuff } } } 

Évidemment, lorsque vous effectuez vos propres implémentations, vous devez prendre en compte la sécurité des threads, qui facilite l’utilisation des transactions, en particulier dans les différents référentiels d’entités.

 // simple example ITransaction t = TransactionFactory.GetNewTransaction(); t.begin(); try{ // create person entity personRepository.Add(person, t); // create cars assigned to person carRepository.AddRange(cars, t); t.commit(); }catch(Exception){ t.rollback(); } 

Assurez-vous simplement que vous voulez vraiment créer votre propre DAL, car il peut être extrêmement complexe, en essayant spécialement de développer la solution la plus générique.

Je suggère d’utiliser un ORM, Entity Framework ou NHibernate fera très bien l’affaire. Ensuite, vous n’avez pas à vous soucier d’un contexte de firebase database ni à créer des instructions SQL.

Tout d’abord, je voudrais vous recommander l’article intitulé Design Patterns for Data Persistence, de Jeremy Miller .

Il existe certains modèles de couche d’access aux données:

  1. Modèle d’enregistrement actif ( wiki , informations détaillées ).
  2. Modèle de référentiel ( informations détaillées ).

Je vous suggère d’utiliser un RepositoryBase pour toutes ces opérations courantes. Si vous décidez d’utiliser un ORM pour accéder aux données, il est bon de penser à une implémentation de référentiels basée sur un référentiel de type générique.

Voici un bon article à ce sujet:

http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/

C’est trop vieux, mais je viens de contourner cette question et je ne pouvais pas résister à poster mes pensées.

J’ai trouvé le repository avec UnitOfWork avec une certaine descendance ORM est une bonne approche. Cela minimise la plupart des problèmes.

Le lien UoW mentionné ci-dessus peut être injecté dans le référentiel. Cela augmente la flexibilité d’utilisation. En outre, tout le code de communication de firebase database est centralisé à un seul endroit. L’exemple n’est pas complet, mais un sharepoint démarrage.

Le modèle de référentiel mentionné dans le lien ci-dessus est en fait une classe de base générique. Vous pouvez créer une nouvelle classe pour chacun de vos référentiels concrets qui en dérive.

Le référentiel générique est considéré comme un modèle anti; il y a beaucoup d’articles sur internet qui l’expliquent.

Pourquoi le référentiel générique est anti-pattern?

  1. Un référentiel est une partie du domaine en cours de modélisation et ce domaine n’est pas générique.
    • Toutes les entités ne peuvent pas être supprimées.
    • Toutes les entités ne peuvent pas être ajoutées
    • Toutes les entités ne disposent pas d’un référentiel.
    • Les requêtes varient énormément; L’API de référentiel devient aussi unique que l’entité elle-même.
    • Pour GetById() , les types d’identifiant peuvent être différents.
    • La mise à jour de champs spécifiques (DML) n’est pas possible.
  2. Le mécanisme de requête générique est la responsabilité d’un ORM.
    • La plupart des ORM exposent une implémentation qui ressemble beaucoup au référentiel générique.
    • Les référentiels devraient implémenter les requêtes SPÉCIFIQUES pour les entités en utilisant le mécanisme de requête générique exposé par ORM.
  3. Travailler avec des clés composites n’est pas possible.
  4. De toute façon, la logique DAL fuit dans les services.
    • Les critères de prédicat si vous acceptez en tant que paramètre doivent être fournis par la couche Service. S’il s’agit d’une classe spécifique à ORM, il fuit ORM dans Services.

Je vous suggère de lire ces articles ( 1 , 2 , 3 , 4 , 5 ) expliquant pourquoi le référentiel générique est un motif anit.

Solution:

  1. Écrivez un référentiel générique abstrait encapsulé dans un référentiel concret. De cette façon, vous pouvez contrôler l’interface publique tout en bénéficiant de la réutilisation de code provenant d’un référentiel générique.
  2. Utilisez un référentiel générique, mais utilisez la composition au lieu de l’inheritance et ne l’exposez pas au domaine en tant que contrat.

Dans tous les cas, n’exposez pas le référentiel générique au code appelant. En outre, n’exposez pas IQueryable partir de référentiels concrets.