Pregunta

Me estoy preparando para iniciar un nuevo proyecto web asp.net y voy a utilizar LINQ-to-SQL.He trabajado un poco para configurar mi capa de datos usando información que encontré Mike Hadlow que utiliza una interfaz y genéricos para crear un repositorio para cada tabla de la base de datos.Al principio pensé que este era un enfoque interesante.Sin embargo, ahora creo que podría tener más sentido crear una clase de Repositorio base y heredarla para crear una clase TableNameRepository para las tablas a las que necesito acceder.

¿Qué enfoque me permitirá agregar funcionalidades específicas a una tabla de una manera limpia y comprobable?Aquí está la implementación de mi repositorio como referencia.

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
}
¿Fue útil?

Solución

Me sentiría tentado a sugerir que no debería importar si usa tipos concretos o no, como si estuviera usando inyección de dependencia (¿castillo?) para crear los repositorios (para que pueda empaquetarlos con diferentes cachés, etc.), entonces su base de código será Ninguno se da cuenta de cualquier manera que lo hayas hecho.

Luego simplemente pídale a su DI un repositorio.P.ej.para castillo:

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

Personalmente, no tocaría fondo con los tipos hasta que encuentre la necesidad de hacerlo.

Supongo que la otra mitad de su pregunta es si puede proporcionar fácilmente una implementación en memoria de IRepository para fines de prueba y almacenamiento en caché.Para esto, tendría que tener cuidado ya que linq-to-objects puede ser lento y es posible que encuentres algo como http://www.codeplex.com/i4o útil.

Otros consejos

No debes crear un repositorio para cada tabla.
En su lugar, debe crear un repositorio para cada 'raíz de entidad' (o raíz agregada) que exista en su modelo de dominio.Puede obtener más información sobre el patrón y ver un ejemplo funcional aquí:

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top