Entity Framework Code - первое сопоставление TpT в составном приложении
Я работаю над составным комплексным системным приложением, в которое разные компании могут добавлять разные модули, но есть только одна база данных. У меня есть универсальный репозиторий, который не зависит от технологии (я имею в виду его базу поставщиков, и на данный момент провайдер дефолта - EF). 4.1). Я разделил общий слой, который содержит объекты Poco, и в каждом модуле также есть различные объекты на модуль. Теперь проблема заключается в отображении сущностей. У меня нет доступа к моим сущностям из моего проекта провайдера EF, так как я не знаю будущих модулей! так как я могу отобразить мои сущности в общем подходе? Является ли это возможным?
Одним из решений, которое я считаю, является наличие файла конфигурации и добавление сущностей FullName, затем итерирование и отражение каждого из них, а затем я могу добавить их в метод OnModelCreat(...), но, конечно, есть некоторые проблемы с производительностью.
Изменить: Во-первых, спасибо за ваш ответ, Ладислав. Но есть еще немного информации для вас.
Вы можете сделать требование, чтобы каждый модуль содержал классы отображения для каждой новой сущности, которую он использует. Когда вы запустите приложение, вы просто будете использовать отражение, чтобы получить все классы, производные от StructuralTypeConfiguration<> (включая как сущности, так и сложные типы), создать экземпляры этих типов и добавить их в коллекцию Configurations в DbModelBuilder (это можно сделать в OnModelCreating).
Это займет некоторое время, но это произойдет только один раз, когда контекст используется впервые. Вы можете запустить это создание во время запуска приложения - приложениям просто нужно некоторое время для запуска и настройки всей инфраструктуры, которую они должны использовать.
Редактировать:
Я должен ссылаться на EntityFramework.dll в каждом модуле, который не подходит в этом случае.
Да. Вы хотите позволить другим разработчикам определять свои собственные объекты, которые будут сохраняться вашим основным приложением. В таком случае они должны использовать вашу постоянную среду выбора, чтобы сообщить вашему приложению, как сохранить свои сущности.
==> Как я уже говорил, EF - не единственный мой DataProvider! У меня должен быть какой-то другой DP, такой как поставщик данных для DB4O и т. Д., Поэтому я не хочу ссылаться на зависимости каждого провайдера для каждого модуля... поэтому мне нужно инкапсулировать EF в отдельную сборку
Если вы используете репозитории, каждый модуль должен даже содержать свои собственные репозитории для работы со своими собственными сущностями - универсальный репозиторий не существует. Универсальный репозиторий является избыточным бесполезным слоем, который только усложняет работу с ORM по вашему выбору. Чтобы было понятно - правильная реализация шаблона репозитория не является общей. Он специфичен и предоставляет функциональные возможности доступа к данным для одного объекта или совокупного корня.
==> Могу ли я попросить любой надежный реф? Зачем мне добавлять один репозиторий на модуль, если только один репозиторий может выполнить все мои требования? что избыточно? По моему мнению, использование определенных или общих повторений является правильным в правильной ситуации.90% моих модулей предъявляют те же требования к хранилищу, и все они должны иметь CRUD ...
Если вам не нужна зависимость EF в модулях, либо вообще не используйте EF, либо определите свой собственный промежуточный уровень отображения, который будет преобразован в конкретное отображение в вашем приложении - большая работа с нулевой добавленной стоимостью.
==> На самом деле я пытаюсь определить свой собственный слой отображения, потому что он мне нужен в моей архитектуре приложения. Это не бесполезно для меня. Это была единственная причина, по которой я спросил, как это реализовать. Я ищу лучшее решение, и я надеюсь, что вы могли бы помочь мне передать его:)
Другой вариант просто не позволяет вашим модулям использовать новые объекты, потому что это больше похоже на ваши текущие ожидания. Если разработчик модуля должен определить новые таблицы базы данных для своих сущностей, он также должен иметь возможность работать с постоянством и определять отображение между таблицами и своими сущностями.
==> Хорошая идея, но не подходит для моего случая;)
Я должен отражать каждый модуль DLL при запуске, что означает, что много тяжелых DLL должны быть отражены, и... Есть ли еще какие-либо идеи?
Вы когда-нибудь видели такие приложения, как Photoshop, Visual Studio или даже приложения MS Office, при запуске? Как вы думаете, что происходит, когда вы видите заставку? Приложение инициализируется - оно загружает и инициализирует его функции и плагины. Даже серверному приложению может потребоваться несколько минут для полного запуска. Вы создаете модульное приложение (не составное), поэтому вы должны заплатить за это требование.
==> Да, я думаю, что видел некоторых из них! Если они загружают, например, все паллеты или боковые панели при запуске, они должны нанять меня. Уважаемый Microsoft, если вы не знаете, что такое отложенная загрузка, я могу помочь вам улучшить вашу производительность:)
Если вы не хотите использовать отражение самостоятельно, вы можете использовать MEF для построения модульной инфраструктуры.
==> Я уже использую Prism и MEF для обработки модульности, но только для модулей, а не для моих провайдеров...
Кажется, что EF не является хорошим решением для корпоративного композитного приложения, верно?
Вы не предложили никаких корпоративных требований, которые не должны выполняться EF. Вы просто боретесь со своими ожиданиями, чтобы позволить разработчикам модулей использовать новые сущности, но не дают им возможности описать, как эти сущности будут сохраняться - но кто это будет описывать?
==> Модель или промежуточный слой отображения, который будет работать в каждом модуле, загружать и отображать сущности, если EF поддерживает (что не может, насколько я знаю), мне нужно что-то вроде начальной загрузки для каждого провайдера для сопоставления сущностей:)
Вы не создаете составное приложение. Составное приложение использует существующие функции (компоненты, существующие приложения), которые работают отдельно, и объединяет их в новое приложение. Вы создаете модульное приложение, в котором ваше ядро может содержать другие модули, но эти модули не могут работать без вашей хостинг-инфраструктуры.
==> Я не собираюсь читать лекцию о моем приложении и его архитектуре, но я думаю, что этого достаточно, чтобы вы знали, что это составное / модульное приложение...
Должен ли я сначала перейти на модель?!!
Первая модель (и EDMX в целом) действительно не подходит для ваших ожиданий, потому что в случае первой модели каждому модулю потребуется собственный файл EDMX и собственный контекст.
==> но я могу изменить модель и XML-файл EDMX во время выполнения, верно?!
Вы также не должны сначала использовать автоматическую генерацию базы данных по коду, потому что любой новый модуль либо сломает ваше приложение, либо EF удалит вашу текущую базу данных.
==> спасибо за этот совет, хотя я знал это раньше, но, конечно, я уделю этому больше внимания.
1 ответ
Вы можете сделать требование, чтобы каждый модуль содержал классы отображения для каждой новой сущности, которую он использует. Когда вы запускаете приложение, вы просто используете отражение, чтобы получить все классы, полученные из StructuralTypeConfiguration<>
(включает как сущности, так и сложные типы), создайте экземпляры этих типов и добавьте их в Configurations
коллекция в DbModelBuilder
(можно сделать в OnModelCreating
).
Это займет некоторое время, но это произойдет только один раз, когда контекст используется впервые. Вы можете запустить это создание во время запуска приложения - приложениям просто нужно некоторое время для запуска и настройки всей инфраструктуры, которую они должны использовать.
Редактировать:
Я должен ссылаться на EntityFramework.dll в каждом модуле, который не подходит в этом случае.
Да. Вы хотите позволить другим разработчикам определять свои собственные объекты, которые будут сохраняться вашим основным приложением. В таком случае они должны использовать вашу постоянную среду выбора, чтобы сообщить вашему приложению, как сохранить свои сущности.
Если вы используете репозитории, каждый модуль должен даже содержать свои собственные репозитории для работы со своими собственными сущностями - универсальный репозиторий не существует. Универсальный репозиторий является избыточным бесполезным слоем, который только усложняет работу с ORM по вашему выбору. Чтобы было понятно - правильная реализация шаблона репозитория не является общей. Он специфичен и предоставляет функциональные возможности доступа к данным для одного объекта или совокупного корня.
Если вам не нужна зависимость EF в модулях, либо вообще не используйте EF, либо определите свой собственный промежуточный уровень отображения, который будет преобразован в конкретное отображение в вашем приложении - большая работа с нулевой добавленной стоимостью.
Другой вариант просто не позволяет вашим модулям использовать новые объекты, потому что это больше похоже на ваши текущие ожидания. Если разработчик модуля должен определить новые таблицы базы данных для своих сущностей, он также должен иметь возможность работать с постоянством и определять отображение между таблицами и своими сущностями.
Я должен отражать каждый модуль DLL при запуске, что означает, что много тяжелых DLL должны быть отражены, и... Есть ли еще какие-либо идеи?
Вы когда-нибудь видели такие приложения, как Photoshop, Visual Studio или даже приложения MS Office, при запуске? Как вы думаете, что происходит, когда вы видите заставку? Приложение инициализируется - оно загружает и инициализирует его функции и плагины. Даже серверному приложению может потребоваться несколько минут для полного запуска. Вы создаете модульное приложение (не составное), поэтому вы должны заплатить за это требование.
Если вы не хотите использовать отражение самостоятельно, вы можете использовать MEF для построения модульной инфраструктуры.
Кажется, что EF не является хорошим решением для корпоративного композитного приложения, верно?
Вы не предложили никаких корпоративных требований, которые не должны выполняться EF. Вы просто боретесь со своими ожиданиями, чтобы позволить разработчикам модулей использовать новые сущности, но не позволяете им описать, как эти сущности будут сохраняться - но кто это будет описывать?
Вы не создаете составное приложение. Составное приложение использует существующие функциональные возможности (компоненты, существующие приложения), которые работают отдельно, и объединяет их в новое приложение. Вы создаете модульное приложение, в котором ваше ядро может содержать другие модули, но эти модули не могут работать без вашей хостинг-инфраструктуры.
Должен ли я сначала перейти на модель?!!
Первая модель (и EDMX в целом) действительно не подходит для ваших ожиданий, потому что в случае первой модели каждому модулю потребуется собственный файл EDMX и собственный контекст.
Вы также не должны сначала использовать автоматическую генерацию базы данных по коду, потому что любой новый модуль либо сломает ваше приложение, либо EF удалит вашу текущую базу данных.
Последнее редактирование, потому что это не дискуссионный форум:
EF не мой единственный DataProvider! У меня должен быть какой-то другой DP, такой как...
Я не знаю, почему вы это делаете, но это неправильно. Одно приложение (даже модульное) должно использовать одного поставщика (ORM mapper). Если у вас есть другие поставщики данных из-за какого-то устаревшего кода, пусть будет так, но вы должны установить политику единого поставщика для всего нового кода. В противном случае вы боретесь с вашим чрезмерно архитектурным приложением, а не с EF. В таком случае ваши модули всегда будут использовать только одну зависимость от провайдера.
Могу ли я попросить любой надежный реф? Зачем мне добавлять один репозиторий на модуль, если только один репозиторий может выполнить все мои требования? что избыточно?
Реф это опыт. Есть сотни вопросов о репозитории и EF. Если вы хотите использовать все преимущества EF, общий репозиторий не позволит этого или ему придется предоставлять функции, которые недоступны в реализациях для других поставщиков. Если вы используете репозиторий просто для того, чтобы выставить CRUD для одной сущности, вы просто оборачиваете IDbSet
уже предоставляет. Я понимаю, что вы используете репозитории, чтобы скрыть ад ваших провайдеров.
На самом деле я пытаюсь определить свой собственный слой отображения, потому что он мне нужен в моей архитектуре приложения. Это не бесполезно для меня.
Вы собираетесь написать какое-то пользовательское сопоставление (возможно, XML) и конвертор для каждого сопоставления конкретного провайдера. Я не уверен, какой лучший ответ вы ожидаете - за исключением того, что это не хороший путь.
Модель или промежуточный слой отображения, который будет работать в каждом модуле, загружать и отображать сущности, если EF поддерживает (что не может, как я знаю), мне нужно что-то вроде начальной загрузки для каждого провайдера для сопоставления сущностей
Это не пропущенная часть EF. Это просто выходит за рамки EF. Любой промежуточный уровень, определенный EF, все еще будет частью EF и не будет поддерживаться другими инструментами. EF может загружать сущности, когда создает модель, но чтобы загрузить их, вы должны сообщить EF об их существовании и о том, как их отобразить, - так объяснял мой первоначальный ответ.
Я не собираюсь читать лекцию о моем приложении и его архитектуре, но я думаю, что этого достаточно, чтобы вы знали, что это составное / модульное приложение.
Это может быть, но у составной части нет этих проблем, потому что каждый компонент составного приложения независим от остальных и может использовать совершенно разную устойчивость. Задача, стоящая перед вами, является внутренней для каждого модульного компонента.
Но я могу изменить модель и XML-файл EDMX во время выполнения, не так ли?
Попытайся. Подсказка: нет общедоступного API для работы с этим XML на низкоуровневой основе, и нет общедоступного API для изменения загруженной модели. Можно изменить EDMX перед загрузкой, но обычно это означает написание собственного анализатора и компоновщика xml для SSDL, MSL и CSDL. У вас будет один набор файлов сопоставления, обновленный всеми установленными модулями. Вам также придется выполнить код обратной операции, чтобы удалить модуль и правильно удалить все функции из сопоставления. Любая ошибка может сломать все ваше приложение, потому что отображение будет повреждено. Моя первоначальная идея с загруженными конфигурациями для отображения кода займет у вас менее одного дня. Сколько времени потребуется, чтобы построить это?
Если вы хотите пойти по этому пути, полностью удалите EF из своего проекта и начните использовать NHibernate и hbm
картографические файлы. Разработчик модуля создаст сборку с логикой модуля и новыми объектами, скриптом для таблиц базы данных и файлом hbm для каждого объекта. Установка модуля создаст таблицу, добавит сборку в расположение модуля и добавит файлы hbm в каталог подбора карт. Ваш сеанс NHibernate загрузит все файлы сопоставления из этого каталога.