Важное редактирование
Нет встроенной поддержки для достижения этого с двумя ObjectContext
типами. Ваш запрос всегда должен выполняться против одного ObjectContext
.
Вероятно, лучший путь: Это было достаточно интересно для меня, чтобы попробовать это сам. Я начал с очень простой идеи. Два файла EDMX (используются с генераторами POCO T4), каждый из которых содержит один объект. Я беру описание метаданных из второй строки подключения и добавляю его в первую строку подключения. Я использовал ObjectContext
и ObjectSet
напрямую. Благодаря этому я смог запросить и изменить обе сущности из одного экземпляра ObjectContext
. Я также попытался создать сущности, соединяющие запросы из обеих моделей, и это сработало.
Это, очевидно, работает, только если оба EDMX отображаются в одну и ту же базу данных (одна и та же строка соединения с БД)
Важной частью является строка соединений:
<configuration>
<connectionStrings>
<add name="TestEntities" connectionString="metadata=res://*/FirstModel.csdl|res://*/FirstModel.ssdl|res://*/FirstModel.msl|res://*/SecondModel.csdl|res://*/SecondModel.ssdl|res://*/SecondModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.;Initial Catalog=Test;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
Эта строка подключения содержит метаданные двух моделей - FirstModel.edmx и SecondModel.edmx.
Другая проблема заключается в том, чтобы заставить EF использовать сопоставление из обоих этих файлов. Каждый файл EDMX должен определять уникальный контейнер для SSDL и CSDL. ObjectContext
предлагает недвижимость под названием DefaultContainerName
. Это свойство может быть установлено напрямую или через некоторые перегрузки конструктора. После установки этого свойства вы привязываете свой экземпляр ObjectContext
к одному EDMX - для этого сценария вы не должны устанавливать это свойство. Пропуск DefaultContainerName
может иметь некоторые последствия, потому что некоторые функции и объявления могут перестать работать (вы получите ошибки во время выполнения). У вас не должно быть проблем с POCO, если вы не хотите использовать некоторые расширенные функции. Скорее всего, у вас возникнут проблемы, если вы используете объекты Entity (тяжелые объекты EF. Все методы, использующие наборы объектов, определенные как строки, зависят от контейнера. В связи с этим я предлагаю использовать такую конфигурацию только при необходимости - для запросов между моделями.
Последняя проблема - генерирование сущностей и производных со строгой типизацией ObjectContext
. Нужно изменить шаблон T4 так, чтобы один шаблон считывал данные из нескольких файлов EDMX и генерировал конечные сущности контекста для всех них - я уже делал это в своем проекте, и это работает. Реализация по умолчанию T4 не следует необходимому подходу, описанному в предыдущем параграфе. Производная ObjectContext
от реализации T4 по умолчанию зависит от одного EDMX и контейнера сущностей.
<Ч />
Эта часть была написана до предыдущего редактирования.
Я оставляю остальную информацию только потому, что некоторые из них могут быть полезны в других сценариях, включая работу с несколькими базами данных.
ORM-подобная структура сущностей работает поверх отображения между миром объектов и миром баз данных. В EF объектный мир описывается как CSDL , мир базы данных описывается как SSDL , а отображение между ними описывается как MSL (все это просто XML с хорошо известными схемы). Во время разработки эти описания являются частью модели, хранящейся в файле EDMX. Во время компиляции эти описания извлекаются из EDMX и по умолчанию включаются как файлы ресурсов в скомпилированную сборку.
Когда вы создаете экземпляр ObjectContext
, он получает строку соединений, которая содержит ссылку на файлы ресурсов CSDL, SSDL и MSL. SSDL или MSL не указывают элемент include для добавления информации из других файлов. CSDL предлагает использование элемента , который позволит вам повторно использовать существующее отображение, но эта функция не поддерживается дизайнером. ConnectionString используется для инициализации экземпляра EntityConnection
, который, в свою очередь, используется для инициализации ObjectContext MetadataWorkspace
(информация отображения во время выполнения). Также ObjectContext
не предоставляет никакой функциональности для вложения нескольких контекстов в hiearchy. Строка подключения не может содержать ссылки на несколько экземпляров этих файлов. Редактировать: Может. Я только что проверил это. См. Первоначальные абзацы.
Когда вы запускаете запрос Linq или ESQL для экземпляра ObjectContext
, он использует MSL, чтобы отобразить ваши сущности или классы POCO (определенные CSDL) в запрос к базе данных (определенный SSDL-описанием таблиц базы данных). Если у него нет этой информации, он не будет работать (и не может иметь эту информацию, если он хранится в отдельном EDMX).
Так как решить эту проблему? Есть несколько способов:
- Всегда учитывайте: Объедините ваше отображение в один файл (если несколько файлов используются для одной базы данных). Это предполагаемый способ использования EF, и, как вы упомянули, вы запрашиваете одну и ту же БД, поэтому две модели EF не нужны.
- Повторяющееся описание сущности во второй модели. Если вы используете EF4 и POCO, вы можете отобразить одни и те же описания из нескольких моделей в одно определение класса POCO. Мне не нравится это решение, но иногда оно может помочь.
- Определите DB View или хранимую процедуру, содержащую ваш запрос (или ядро вашего запроса), и сопоставьте его в одной модели с новым объектом.
- Используйте DefiningQuery в одной модели (вам, вероятно, понадобится третья, если вы используете функцию обновления из базы данных), и сопоставьте ее с новой сущностью. DefiningQuery - это пользовательский SQL-запрос, определенный в SSDL вместо описания таблицы или представления.
- Использовать Функция с пользовательским CommandText, определяющим запрос БД. Это похоже на использование DefiningQuery и имеет такое же ограничение. Вы должны вручную (в EDMX) отобразить результат функции в новый сложный тип (еще одно отличие от DefiningQuery, которое сопоставлено с новым объектом).
- Определите новый тип для результата запроса (свойства типа должны иметь те же имена, что и возвращаемые столбцы в запросе) и использовать ObjectContext's ExecuteStoreQuery (только в EF4).
Разделите запрос на две части, каждая из которых выполняется отдельно в своем собственном контексте, и используйте linq-to-objects для получения результата. Мне не нравится это решение.
Это только идея высокого уровня - я не пробовал ее и не знаю, работает ли она. Как описано выше, отображение во время выполнения зависит от содержимого MetadataWorkspace
экземпляр, который заполнен от EntityConnection
. EntityConnection
также предоставляет конструктор, который получает экземпляр MetadataWorkspace
напрямую. Поэтому, как правило, если будет возможно заполнить MetadataWorkspace
из нескольких EDMX, вам не понадобится несколько экземпляров ObjectContext, но ваше отображение будет по-прежнему разделено на два EDMX. Надеемся, что это позволит вам писать собственные запросы Linq поверх двух файлов сопоставления). Редактировать: Это должно быть возможно, потому что это именно то, что делает EF, если вы определяете несколько отображений в строке подключения.
Использование CSDL Использование функции для разбиения модели на несколько повторно используемых частей.