По мере того, как я углубляюсь в DbContext, DbSet и связанные с ними интерфейсы, я удивляюсь, почему вам нужно реализовать отдельный «универсальный» репозиторий вокруг этих реализаций?
Похоже, что DbContext и IDbSet делают все, что вам нужно, и включают «Единицу работы» внутри DbContext.
Я что-то здесь упускаю или кажется, что людям нравится добавлять еще один уровень зависимости без причины.
Ответы:
Вы на самом деле правы.
DbContext
является реализацией шаблона единицы работы иIDbSet
является реализацией шаблона репозитория.Хранилища в настоящее время очень популярны и чрезмерно используются. Все используют их только потому, что существуют десятки статей о создании репозитория для структуры сущностей, но на самом деле никто не описывает проблемы, связанные с этим решением.
Основными причинами использования репозитория обычно являются:
Первая причина - это некая архитектурная чистота и отличная идея, что если вы сделаете свои верхние уровни независимыми от EF, вы сможете позже переключиться на другую среду персистентности. Сколько раз вы видели такую вещь в реальном мире? Эта причина значительно усложняет работу с EF, поскольку в вашем хранилище должно быть много дополнительных функций, охватывающих то, что EF позволяет по умолчанию.
В то же время упаковка EF-кода может улучшить организацию вашего кода и следовать правилу разделения интересов. Для меня это может быть единственным реальным преимуществом репозитория и единицы работы, но вы должны понимать, что следование этому правилу с EF, возможно, сделает ваш код лучше поддерживаемым и лучше читаемым, но при первоначальных усилиях по созданию вашего приложения оно будет намного выше и для небольших приложений это может быть ненужной сложностью.
Вторая причина частично верна. Большим недостатком EF является жесткая архитектура, которую трудно подделать, поэтому, если вы хотите выполнить модульное тестирование верхнего уровня, вы должны каким-то образом обернуть EF, чтобы допустить насмешку над его реализацией. Но это имеет много других последствий, которые я описал здесь .
Я слежу за блогом Айенде . Если вы когда-либо использовали NHibernate, вы, вероятно, знаете его статьи. Этот парень недавно написал несколько статей против использования репозитория с NHibernate, но NHibernate гораздо лучше подшучивает.
источник
IDbSet
вы также можете определить пользовательский интерфейс в производном контексте, но это все. Как только ваш код использует ChangeTracker, Entries или что-то еще, потребуется много усилий, чтобы обернуть их все.IQueryable
или принимает вExpression<>
качестве параметра, который внутренне помещается в запрос Linq-to-entity, вы определяете логику вне смоделированного компонента с побочными эффектами, которые невозможно проверить с помощью модульных тестов.Я борюсь с теми же проблемами, и важна насмешливость для модульного тестирования слоев EF. Но я наткнулся на эту замечательную статью, в которой объясняется, как настроить EF 4.1 DbContext для подделки, убедившись, что ваш производный DbContext реализовал общий интерфейс и предоставляет IDbSet, а не DbSet. Поскольку я использую подход Database First, поскольку наша база данных уже существует, я просто изменил шаблоны T4, использованные для генерации моего производного DbContext, чтобы он генерировал интерфейсы IDbSet, а также производные от моего общего интерфейса. Таким образом, все это может быть легко смоделировано, и вам не нужно реализовывать собственную единицу работы или шаблон репозитория. Просто напишите свой сервисный код, чтобы использовать ваш общий интерфейс, и когда вы перейдете к его тестированию,
http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/
источник
Одна из причин создания репозитория заключается в том, что вы можете скрыть реализацию DBSet и DbContext, если решите перейти от EntityFramework к чему-то другому или наоборот.
Например, я использовал NHibernate, и я обернул все вызовы этой платформы в свои классы репозитория. Они возвращают IEnumerable для того, чтобы они были «общими», а мои репозитории имеют стандартные операции CRUD (обновление, удаление и т. Д.). Я давно перешел на Entity Framework. После этого мне не нужно было ничего менять в моих классах ViewModel или за их пределами, потому что они указывали на мой репозиторий - мне нужно было только изменить внутреннюю часть своего репозитория. Это значительно облегчило жизнь при миграции.
(Я использовал NHibernate, потому что мы подключаемся к ISeries, и в то время не было экономически эффективных реализаций, использующих EF с ISeries. Единственной доступной была оплата IBM $ 12 000 за их DB2Connect)
источник