Вопрос

Я готовлюсь начать новый веб-проект asp.net и собираюсь использовать LINQ-to-SQL.Я проделал небольшую работу по настройке уровня данных, используя некоторую информацию, которую нашел Майк Хэдлоу который использует интерфейс и дженерики для создания репозитория для каждой таблицы в базе данных.Сначала мне показалось, что это интересный подход.Однако теперь я думаю, что, возможно, имеет смысл создать базовый класс Repository и наследовать его, чтобы создать класс TableNameRepository для таблиц, к которым мне нужен доступ.

Какой подход позволит мне добавить функциональность, специфичную для таблицы, простым и доступным для тестирования способом?Вот моя реализация репозитория для справки.

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
}
Это было полезно?

Решение

У меня возникнет искушение предположить, что не имеет значения, используете ли вы конкретные типы или нет, как если бы вы использовали внедрение зависимостей (замок?) для создания репозиториев (чтобы вы могли обернуть их разными кешами и т. д.), тогда ваша кодовая база будет какой бы способ вы это ни сделали, никто не станет мудрее.

Затем просто попросите у своего DI репозиторий.Например.для замка:

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

Лично я бы не стал останавливаться на типах, пока вы не найдете в этом необходимость.

Полагаю, другая половина вашего вопроса заключается в том, можете ли вы легко предоставить реализацию IRepository в памяти для целей тестирования и кэширования.Для этого я бы остерегался, поскольку linq-to-objects может быть медленным, и вы можете найти что-то вроде http://www.codeplex.com/i4o полезный.

Другие советы

Не следует создавать репозиторий для каждой таблицы.
Вместо этого вам следует создать репозиторий для каждого «корня объекта» (или совокупного корня), существующего в вашей модели предметной области.Вы можете узнать больше о шаблоне и увидеть рабочий пример здесь:

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top