Question

Je me prépare à démarrer un nouveau projet Web asp.net et je vais à LINQ-to-SQL. J'ai un peu travaillé sur la configuration de la couche de données en utilisant certaines 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, je pense qu’il serait peut-être plus logique de créer une classe de référentiel de base et d’en hériter pour créer une classe TableNameRepository pour les tables auxquelles je dois accéder.

Quelle approche me permettra d’ajouter des fonctionnalités spécifiques à une table de manière testable? Voici mon implémentation de 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
}
Était-ce utile?

La solution

Je serais tenté de suggérer que peu importe que vous utilisiez des types concrets ou non, comme si vous utilisiez une injection de dépendance (château?) pour créer les référentiels (afin que vous puissiez les envelopper avec différents caches, etc.), votre Codebase ne sera pas le plus sage de la façon dont vous l'avez fait.

Ensuite, demandez simplement à votre DI un référentiel. Par exemple. pour le château:

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

Personnellement, je ne rédigerais pas les types tant que vous n'en auriez pas besoin.

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

Autres conseils

Vous ne devez pas créer de référentiel pour chaque table.
Vous devez plutôt créer un référentiel pour chaque "racine d'entité" (ou racine d'agrégat) présente dans votre modèle de domaine. Vous pouvez en savoir plus sur le modèle et voir un exemple de travail ici:

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top