Один большой репозиторий против множества маленьких? - PullRequest
13 голосов
/ 10 июня 2011

В моей базе данных есть несколько таблиц продуктов:

  • ProductTypes
  • ProductCategories
  • ProductCategoryItems
  • ProductInventory

Как я сейчас вижу, я могу сделать IProduct, который бы имел такие методы, как:

  • FindAllTypes ()
  • FindAllCategories (int typeId)
  • FindAllItems (int categoryId)

Или, я могу разделить каждый из них, чтобы имитировать структуру таблицы: IProductType, IProductCategory и т. Д.

Есть ли причина переходить один на другой?

Ответы [ 4 ]

13 голосов
/ 10 июня 2011

Идея репозиториев состоит в том, чтобы передать каждому из них ответственность за отдельную сущность.В этом случае рекомендуется создать репозиторий для каждого объекта.Вы также можете выбрать большой репозиторий, но это не лучшее решение.В конце концов вы получите ОГРОМНЫЙ класс с множеством методов и очень тесной связью.Также трудно дать обслуживание.

6 голосов
/ 10 июня 2011

Я не думаю, что иметь огромный репозиторий - это действительно хорошая идея, тогда у вас, в основном, есть класс бога доступа к данным, который делает все.

Мне нравится иметь базу Repository<T>, которая выполняет обычные операции, такие как GetById и GetAll. У меня обычно все мои репозитории наследуют этот базовый класс, чтобы бесплатно получить общие методы, поэтому мне не нужно постоянно переписывать один и тот же код.

4 голосов
/ 10 июня 2011

По моему мнению, это очень сильно зависит от модели бизнес-домена, очень важно определить, какие ваши основные бизнес-объекты.Не обязательно каждая таблица в БД напрямую связана с бизнес-объектом.Таблицы являются просто представлениями вашей одной или нескольких сущностей в нормализованном виде для реляционных баз данных.

Попытайтесь представить свою модель предметной области вне ограничений нормализованных реляционных баз данных, действительно ли существует более одной бизнес-концепции?Репозитории должны быть построены вокруг надежных, цельных, первоклассных бизнес-объектов.

Мой совет - иметь IProductRepository с необходимыми методами для реализации операций CRUD и расширять его по мере необходимости.Вы не хотите получать слишком амбициозные интерфейсы, потому что вам может не понадобиться большая их часть, и это может быть бременем.Важная вещь об интерфейсах состоит в том, чтобы отделить ваш код от схемы персистентности, чтобы вы впоследствии могли предложить гибкость для переключения между ними.

Возможно, в будущем бизнесу потребуется перейти к более подробному представлению -например, поставщики продукта, и в этот момент вы будете использовать свое здравое суждение, чтобы принять решение о том, представляет ли собой важный бизнес-объект, достойный выделенного хранилища или нет.

Надеюсь, это поможет.

3 голосов
/ 10 июня 2011

Я не согласен с остальными (отредактируйте: кроме Исаака). Небольшие хранилища - это фасад (а не шаблон).

Если типы сущностей связаны (имеют навигационные свойства друг с другом), то они на самом деле не разделяемы.

Изменение одного типа объекта и фиксация изменений могут зафиксировать изменение для другого.

Кроме того, вы не можете создать небольшой репозиторий над той же единицей работы, поскольку ORM имеет только ограниченное количество объектов, сопоставленных с базой данных.

Разделите вашу модель на разделяемые домены и создайте одну конкретную единицу работы для каждого домена.

На этих единицах работ создайте агрегированные корни для каждого типа объекта, к которому вам может потребоваться немедленный доступ.

В каждом корне должны быть специально введенные методы add, remove, getbykeys, query и т. Д.

Единица работы должна содержать коммитчаны и аналогичные методы.

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

Пример: * * один тысяча двадцать-одна

// Create one of these
interface IUnitOfWork
{
    void Commit();
}

// Create one of these
interface IEntitySet<TEntity> where TEntity : class
{
    void Add(TEntity entity);
    void Remove(TEntity entity);
    TEntity Create<TSpecificEntity>() where TSpecificEntity : TEntity;

    IQueryable<TEntity> Query();
}

// Create one of these per entity type
interace IEntitySetOfTEntity1 : IEntitySet<Entity1>
{
    TEntity1 GetByKeys(int key1);
}

interace IEntitySetOfTEntity2 : IEntitySet<Entity2>
{
    TEntity1 GetByKeys(short key1, short key2);
}

// Create one of these per separatable domain
interface IDomain1UnitOfWork : IUnitOfWork
{
    IEntitySetOfTEntity1 Entity1s
    {
        get;
    }

    IEntitySetOfTEntity2 Entity2s
    {
        get;
    }
}

Все эти интерфейсы и их реализации могут генерироваться автоматически.

Эти интерфейсы и их реализации очень легкие и ни в коем случае не являются "ОГРОМНЫМ классом с большим количеством методов". Так как они могут генерироваться автоматически, обслуживание просто.

Специальные интерфейсы могут быть добавлены к интерфейсам IDomain1UnitOfWork, IEntitySetOfTEntity1 и т. Д. С помощью:
а. методы расширения
б. частичные интерфейсы и классы (менее рекомендуется, так как это приводит к менее чистому DAL)

Интерфейсы, подобные IEntitySetOfTEntity1, можно игнорировать, если вы используете методы расширения для добавления методов GetByKeys () в IEntitySet .

...