Единый репозиторий с общими методами ... плохая идея? - PullRequest
1 голос
/ 21 февраля 2012

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

public interface IRepository
{
    T GetSingle<T>(IQueryBase<T> query) where T : BaseEntity;

    IQueryable<T> GetList<T>(IQueryBase<T> query) where T : BaseEntity;

    T Get<T>(int id) where T : BaseEntity;

    int Save<T>(T entity) where T : BaseEntity;

    void DeleteSingle<T>(IQueryBase<T> query) where T : BaseEntity;

    void DeleteList<T>(IQueryBase<T> query) where T : BaseEntity;
}

Таким образом, я могу просто добавить один репозиторий в класс и использовать его, чтобы получить все, что мне нужно.

(кстати, я использую Fluent NHibernate в качестве своего ORM с шаблоном сеанса для каждого веб-запроса и внедряю свой репозиторий с помощью Structuremap)

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

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

заранее спасибо за любые предложения.

Ответы [ 5 ]

4 голосов
/ 22 февраля 2012

В настоящее время я использую смесь как общих репозиториев (IRepository<T>), так и пользовательских (ICustomRepository).Я не выставляю IQueryable или IQueryOver из своих репозиториев.

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

Я обнаружил, что определенно не могу делать все из универсального репозитория, но они определенно полезны в ряде случаев.

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

3 голосов
/ 22 февраля 2012

Я сделал нечто подобное в своих проектах.Недостатком является то, что вам нужно быть осторожным, чтобы не создавать ошибку выбора n + 1.Я обошел это, передав отдельный список свойств, чтобы охотно получить.

Главный аргумент против оборачивания вашего ORM таким образом, что это утечка абстракции.Вам все равно придется кодировать некоторые «ошибки», такие как select n + 1, и вы не сможете в полной мере воспользоваться такими вещами, как поддержка кэширования NH (по крайней мере, без дополнительного кода).

Вот хорошая тема о плюсах и минусах этого подхода в блоге Айенде.Он более или менее против этого паттерна, но есть и несколько контраргументов.

2 голосов
/ 22 февраля 2012

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

Если вы не ожидаете изменения в хранилище данных, то есть перехода от БД к текстовому файлу или XML - что никогда не былодело для меня, лучше всего использовать ISession.Вы пытаетесь абстрагировать свой доступ к данным, и это именно то, что делает NHibernate.Использование ограничений репозитория действительно полезных функций, таких как Fetch (), FetchMany (), фьючерсы и т. Д. ISession - это ваша единица работы.

Используйте NHibernate и используйте ISession напрямую!

2 голосов
/ 22 февраля 2012

Я реализовал такой репозиторий для NHibernate. Вы можете увидеть пример здесь .

В этой реализации вы можете выполнять загрузку и выборку. Подводный камень в том, что с NH вам часто потребуется возможность использовать QueryOver или Criteria API для доступа к данным (к сожалению, поставщик LINQ все еще далек от совершенства). И с такой абстракцией это может стать проблемой, приводящей к утечке абстракции.

0 голосов
/ 21 февраля 2012

Я успешно использовал этот подход в нескольких проектах.Это становится обременительной передачей многих IRepository<T> моим уровням обслуживания для каждого BaseEntity, но это работает.Одна вещь, которую я бы изменил, это поставить where T : на интерфейс, а не методы

public interface IRepository<T> where T : BaseEntity
...