Как мне реализовать шаблон репозитория для сложных объектных моделей?

21

Наша модель данных насчитывает почти 200 классов, которые можно разделить примерно на дюжину функциональных областей. Было бы неплохо использовать домены, но разделение не такое чистое, и мы не можем его изменить.

Мы переделываем наш DAL для использования Entity Framework, и большинство рекомендаций, которые я видел, предлагают использовать шаблон Repository. Тем не менее, ни один из примеров не имеет дело со сложными объектными моделями. Некоторые реализации, которые я обнаружил, предлагают использовать репозиторий для каждой сущности. Это кажется смешным и неприемлемым для больших и сложных моделей.

Действительно ли необходимо создавать UnitOfWork для каждой операции и репозиторий для каждой сущности? Я мог бы закончить с тысячами классов. Я знаю, что это неразумно, но я нашел очень мало рекомендаций по реализации Repository, Unit Of Work и Entity Framework для сложных моделей и реалистичных бизнес-приложений.

Эрик Фальскен
источник

Ответы:

6

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

Имеет ли смысл сохранять эту сущность в одиночку?

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

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

марко-fiset
источник
Хорошая ссылка! Я проверяю это.
Эрик Фальскен
Ваша ссылка (и ответ) были самыми полезными, хотя в итоге я не использовал предоставленные шаблоны. В итоге я использовал класс-оболочку, который проксировал методы Add / Attach / Remove / SaveChanges для работы в качестве универсального репозитория, а затем добавил метод Query / QuerySingle / QueryAll, который принимает пользовательские классы запросов для хранения реализации моего запроса. Это хорошо работает, так что я могу выполнять запросы как LINQ, так и T-SQL без непосредственного участия EF.
Эрик Фальскен,
Entity Framework с использованием транзакций уже является реализацией шаблона Unit of Work.
Грег Бургхардт
1
ссылка мертва ...
Newtopian
3

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

Ваши различные функциональные области могут быть ограниченным контекстом . Существуют различные методы для работы с перекрывающимися ограниченными контекстами, если разделение между ними не ясно.

guillaume31
источник
0

Какой теоретический фундамент вы нашли для проектирования базы данных «Шаблон репозитория»? Я не угадал ни одного. Это сложный слой, основанный на поддельной предпосылке: «постоянный слой» - это то, от чего вам нужно быть изолированным. Судя по тому, что я могу сказать, это влияет на широко распространенное в программировании незнание принципов реляционного проектирования и способствует предполагаемой центральности разработки ОО приложения. Но это не оправдывает его существование на рациональных, не говоря уже о теоретических, основаниях.

Единый верный путь к проектированию базы данных не изменился за 30 лет: проанализируйте данные. Найдите ключи и ограничения, а также отношения многие-к-одному. Создайте свои столы в соответствии с обычной формой Бойса-Кодда. Используйте представления и хранимые процедуры для облегчения доступа к данным.

Хотя это может быть нелюбимым, СУБД SQL обеспечивает лучший уровень изоляции, чем все, что может предоставить программист. Это правда, что при изменении базы данных SQL, используемый для доступа к ней, может измениться. Но обратите внимание, что это так, независимо от того, существует ли посреднический уровень . Пока приложение использует представления и хранимые процедуры для доступа к СУБД, обычные средства разработки SQL будут указывать, когда изменения в базовой базе данных делают эти представления и хранимые процедуры недействительными.

В этом и заключается проблема, конечно. Посреднический уровень обеспечивает иллюзию изоляции и комфорт для программиста при написании кода, что он знает, как делать. Изучение дизайна базы данных и SQL требует изучения чего-то нового. Большинство людей предпочли бы умереть, чем думать, и многим это удалось.

Кто-то из вашей команды, несомненно, возразит, что написание SQL для поддержки ваших 200 классов - большая работа. Без сомнения. Но, по крайней мере, это полезная работа. Если вы проектируете базу данных, имитируя ваш ОО-проект, вы также будете выполнять большую часть работы, большая часть которой бесполезна, и побеждать большую часть того, что предлагает вам СУБД.

Например, вы рассматриваете возможность отражения единицы работы в базе данных (я полагаю, в виде таблицы или таблиц). Единица работы является встроенной службой СУБД: begin transaction... обновление базы ... commit transaction. Ничего не моделировать, кроме сопоставления ваших классов с таблицами базы данных в SQL.

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

Джеймс К. Лоуден
источник