2008-09-19 7 views
0

Je me prépare à démarrer un nouveau projet web asp.net, et je vais passer à LINQ-to-SQL. J'ai fait un peu de travail pour obtenir la configuration de ma couche de données en utilisant des informations trouvées par Mike Hadlow qui utilise une interface et des génériques pour créer un référentiel pour chaque table de la base de données. Je pensais que c'était une approche intéressante au début. Cependant, maintenant je pense qu'il pourrait être plus logique de créer une classe Repository de base et d'en hériter pour créer une classe TableNameRepository pour les tables auxquelles j'ai besoin d'accéder.Expérience de l'implémentation du modèle de référentiel

Quelle approche me permettra d'ajouter des fonctionnalités spécifiques à une table d'une manière propre et testable? Voici ma mise en œuvre du référentiel pour référence.

public class Repository<T> : IRepository<T> where T : class, new() 
{ 
    protected IDataConnection _dcnf; 

    public Repository() 
    { 
     _dcnf = new DataConnectionFactory() as IDataConnection; 
    } 

    // Constructor injection for dependency on DataContext 
    // to actually connect to a database 
    public Repository(IDataConnection dc) 
    { 
     _dcnf = dc; 
    } 

    /// <summary> 
    /// Return all instances of type T. 
    /// </summary> 
    /// <returns>IEnumerable<T></returns> 
    public virtual IEnumerable<T> GetAll() 
    { 
     return GetTable; 
    } 

    public virtual T GetById(int id) 
    { 
     var itemParam = Expression.Parameter(typeof(T), "item"); 
     var whereExp = Expression.Lambda<Func<T, bool>> 
      (
       Expression.Equal(
        Expression.Property(itemParam, PrimaryKeyName), 
        Expression.Constant(id) 
       ), new ParameterExpression[] { itemParam } 
      ); 
     return _dcnf.Context.GetTable<T>().Where(whereExp).Single(); 
    } 

    /// <summary> 
    /// Return all instances of type T that match the expression exp. 
    /// </summary> 
    /// <param name="exp"></param> 
    /// <returns>IEnumerable<T></returns> 
    public virtual IEnumerable<T> FindByExp(Func<T, bool> exp) 
    { 
     return GetTable.Where<T>(exp); 
    } 

    /// <summary>See IRepository.</summary> 
    /// <param name="exp"></param><returns></returns> 
    public virtual T Single(Func<T, bool> exp) 
    { 
     return GetTable.Single(exp); 
    } 

    /// <summary>See IRepository.</summary> 
    /// <param name="entity"></param> 
    public virtual void MarkForDeletion(T entity) 
    { 
     _dcnf.Context.GetTable<T>().DeleteOnSubmit(entity); 
    } 

    /// <summary> 
    /// Create a new instance of type T. 
    /// </summary> 
    /// <returns>T</returns> 
    public virtual T Create() 
    { 
     //T entity = Activator.CreateInstance<T>(); 
     T entity = new T(); 
     GetTable.InsertOnSubmit(entity); 
     return entity; 
    } 

    /// <summary>See IRepository.</summary> 
    public virtual void SaveAll() 
    { 
     _dcnf.SaveAll(); 
    } 

    #region Properties 
    private string PrimaryKeyName 
    { 
     get { return TableMetadata.RowType.IdentityMembers[0].Name; } 
    } 

    private System.Data.Linq.Table<T> GetTable 
    { 
     get { return _dcnf.Context.GetTable<T>(); } 
    } 

    private System.Data.Linq.Mapping.MetaTable TableMetadata 
    { 
     get { return _dcnf.Context.Mapping.GetTable(typeof(T)); } 
    } 

    private System.Data.Linq.Mapping.MetaType ClassMetadata 
    { 
     get { return _dcnf.Context.Mapping.GetMetaType(typeof(T)); } 
    } 
    #endregion 
} 
+0

Vous ne demandez pas une question spécifique. – ddaa

+0

Rendez votre question claire ou elle sera fermée comme "pas une vraie question" – aku

Répondre

1

Je serais tenté de dire que si vous utilisez des types concrets ou non ne devrait pas d'importance, comme si vous utilisez l'injection de dépendance (château?) Pour créer les dépôts (de sorte que vous pouvez les envelopper avec des caches différentes etc) alors votre base de code ne sera pas la plus sage de quelque façon que vous l'avez fait.

Ensuite, il suffit de demander votre DI pour un dépôt. Par exemple. pour le château:

public class Home { 
    public static IRepository<T> For<T> { 
    get { 
     return Container.Resolve<IRepository<T>>(); 
    } 
    } 
} 

Personnellement, je ne voudrais pas bas les types jusqu'à ce que vous en ayez besoin.

Je suppose que l'autre moitié de votre question est de savoir si vous pouvez facilement fournir une implémentation en mémoire de IRepository à des fins de test et de mise en cache. Pour cela, je ferais attention car les linq-to-objects peuvent être lents et vous pourriez trouver quelque chose comme http://www.codeplex.com/i4o utile.

5

Vous ne devez pas créer de référentiel pour chaque table. Au lieu de cela, vous devez créer un référentiel pour chaque 'racine d'entité' (ou racine d'agrégat) qui existe dans votre modèle de domaine. Vous pouvez en apprendre davantage sur le modèle et voir un exemple de travail ici:

http://deviq.com/repository-pattern/

Questions connexes