Составлять запросы по моделям данных сущностей - PullRequest
11 голосов
/ 12 февраля 2011

Есть ли способ составлять запросы из 2 разных моделей сущностей, если модели обращаются к одной и той же базовой базе данных.

У меня есть такой сценарий: у меня есть структура, использующая EF для доступа к данным. (EDM 1) У меня есть клиентское приложение, которое использует службы инфраструктуры, а также использует EF для собственного доступа к данным. (EDM2)

В некоторых ситуациях мне нужно составлять запросы и объединяться в объекты, охватывающие 2EDM.

Есть ли способ сделать это без получения данных в памяти от первого EDM, а затем применить дополнительные предикаты / объединения в памяти от сущностей 2-го EDM?

НадеюсьЯ формулирую это правильно

РЕДАКТИРОВАТЬ @ Ладислав Мрнка: Первый EDM - это уровень доступа к данным для многоразовой среды.Нет смысла связывать сгенерированные EF сущности из этого EDM с сущностями потребляющего клиента. Если бы я это сделал, это лишило бы возможности API повторно, и мне пришлось бы иметь дело с дополнительным раздуванием (метаданные EF и таблицы БД клиента) каждый раз, когда я хотел заново развернуть фреймворк.Кроме того, это может сделать управление моделью в конструкторе громоздким.

В настоящее время я использую то, что вы упоминаете в пункте 7, как решение, и производительность ужасна из-за того, что мне приходится возвращать больше данных.(т. е. сущностей), чем это необходимо, из структуры, использующей EDM1, а затем отфильтровывают ненужные на основе предикатов / условий на основе значений свойств от сущностей во втором EDM.Конечным результатом является значительное снижение производительности и несчастный администратор базы данных.

По этой причине я закончил толкать логику, необходимую для извлечения сущностей в SPROC, в котором я могу получить доступ к таблицам, которые используют оба EDM, и применить предикатынеобходимо, чтобы весь запрос выполнялся в БД, а не вносил данные в память, а затем отфильтровывал ненужные. Недостатком является то, что я не могу использовать LINQ

Item 8, который, как вы упомянули, звучит интересно, но из чегоПохоже, я сомневаюсь, что вы набираете сильные тексты во время разработки или нет?Можете ли вы загрузить пример кода где-нибудь, чтобы я смог его опробовать?

1 Ответ

5 голосов
/ 13 февраля 2011

Важное редактирование

Нет встроенной поддержки для достижения этого с двумя 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=&quot;Data Source=.;Initial Catalog=Test;Integrated Security=True;MultipleActiveResultSets=True&quot;" 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).

Так как решить эту проблему? Есть несколько способов:

  1. Всегда учитывайте: Объедините ваше отображение в один файл (если несколько файлов используются для одной базы данных). Это предполагаемый способ использования EF, и, как вы упомянули, вы запрашиваете одну и ту же БД, поэтому две модели EF не нужны.
  2. Повторяющееся описание сущности во второй модели. Если вы используете EF4 и POCO, вы можете отобразить одни и те же описания из нескольких моделей в одно определение класса POCO. Мне не нравится это решение, но иногда оно может помочь.
  3. Определите DB View или хранимую процедуру, содержащую ваш запрос (или ядро ​​вашего запроса), и сопоставьте его в одной модели с новым объектом.
  4. Используйте DefiningQuery в одной модели (вам, вероятно, понадобится третья, если вы используете функцию обновления из базы данных), и сопоставьте ее с новой сущностью. DefiningQuery - это пользовательский SQL-запрос, определенный в SSDL вместо описания таблицы или представления.
  5. Использовать Функция с пользовательским CommandText, определяющим запрос БД. Это похоже на использование DefiningQuery и имеет такое же ограничение. Вы должны вручную (в EDMX) отобразить результат функции в новый сложный тип (еще одно отличие от DefiningQuery, которое сопоставлено с новым объектом).
  6. Определите новый тип для результата запроса (свойства типа должны иметь те же имена, что и возвращаемые столбцы в запросе) и использовать ObjectContext's ExecuteStoreQuery (только в EF4).
  7. Разделите запрос на две части, каждая из которых выполняется отдельно в своем собственном контексте, и используйте linq-to-objects для получения результата. Мне не нравится это решение.

  8. Это только идея высокого уровня - я не пробовал ее и не знаю, работает ли она. Как описано выше, отображение во время выполнения зависит от содержимого MetadataWorkspace экземпляр, который заполнен от EntityConnection. EntityConnection также предоставляет конструктор, который получает экземпляр MetadataWorkspace напрямую. Поэтому, как правило, если будет возможно заполнить MetadataWorkspace из нескольких EDMX, вам не понадобится несколько экземпляров ObjectContext, но ваше отображение будет по-прежнему разделено на два EDMX. Надеемся, что это позволит вам писать собственные запросы Linq поверх двух файлов сопоставления). Редактировать: Это должно быть возможно, потому что это именно то, что делает EF, если вы определяете несколько отображений в строке подключения.

  9. Использование CSDL Использование функции для разбиения модели на несколько повторно используемых частей.

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