Опыт внедрения шаблонов репозитория - PullRequest
0 голосов
/ 19 сентября 2008

Я готовлюсь начать новый веб-проект asp.net и собираюсь перейти на LINQ-to-SQL. Я проделал небольшую работу по настройке уровня данных, используя некоторую информацию, найденную Mike Hadlow , которая использует интерфейс и универсальные элементы для создания репозитория для каждой таблицы в базе данных. Сначала я подумал, что это интересный подход. Однако теперь я думаю, что было бы более разумно создать базовый класс 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
}

Ответы [ 2 ]

5 голосов
/ 08 февраля 2011

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

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

1 голос
/ 19 сентября 2008

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

Тогда просто спросите своего 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 полезным.

...