1

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

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)

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

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

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

+0

Это вопрос, основанный на мнениях. Все ответы пока подтверждают то же самое. С небольшими изменениями этот вариант подходит для https://softwareengineering.stackexchange.com/. –

ответ

4

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

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

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

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

+0

Я использую этот метод, но я открываю IQueryOver и даже Session из моего репозитория, и это дает мне возможность разрешить NHibernate в мои контрольные или вспомогательные классы. Хорошо работает для меня. – Rippo

0

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

public interface IRepository<T> where T : BaseEntity 
3

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

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

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

2

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

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

2

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

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

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

+1

Я нахожу, что шаблон хранилища значительно облегчает модульный тест моего кода, который использует репозитории. –

+0

@ColeW - Я использую sqlite в базе данных памяти с моими испытаниями. Это быстро, и мне не нужно создавать дополнительный слой поверх ISession. Я использовал IRepository, но как только я переключился на ISession, было намного проще работать с NHibernate. –

+0

@ToniParviainen Я говорю об модульных тестах. Вы говорите об интеграционных тестах. –

Смежные вопросы