Опыт реализации шаблона репозитория

Я собираюсь начать новый веб-проект 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
}

Вы не задаете конкретный вопрос.

ddaa 19.09.2008 18:24

Четко сформулируйте свой вопрос, иначе он будет закрыт как «не настоящий вопрос».

aku 19.09.2008 18:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
2 680
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

Тогда просто попросите своего 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/

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