Entity Framework - Обновление схемы, несколько СУБД и сначала код - PullRequest
2 голосов
/ 03 апреля 2011

Я изучаю возможность использования Entity Framework от Microsoft в будущем проекте, который представляет собой точечный выпуск существующего продукта. Наш текущий продукт поддерживает две СУБД (Oracle и SQL Server), схема каждой из которых поддерживается в отдельных файлах скриптов .sql.

Структура сущностей (4.1) выглядит привлекательно, поскольку позволяет автоматически реализовывать различные сценарии с помощью генерации кода, отражения и т. Д. Однако, насколько я могу судить, некоторые из этих преимуществ кажутся взаимоисключающими другие.

Например, чтобы поддерживать несколько DMBS, я делаю вывод, что мне нужно будет использовать модель или код сначала, в этом случае EF сгенерирует схему для каждого в соответствии с моделью (я почти не видел сообщений или документация на это, так что я могу ошибаться). Это означает, что наша существующая схема должна быть либо отменена (сначала модель), либо отображена (сначала код). Кроме того, для обновления схемы потребуются ручные сценарии, поскольку EF не поддерживает обновления схемы (без удаления данных).

  1. Являются ли модель-первый и код-первый единственным жизнеспособным средством поддержки нескольких СУБД в EF? Я понимаю, что технически было бы невозможно гарантировать, что две произвольные схемы совпадают, поэтому я думаю, что это правда.
  2. Существуют ли потенциальные ловушки при кодировании в первую очередь и при сопоставлении с несколькими системами СУБД? Например, в Oracle нет столбцов с автоинкрементом; Вы должны использовать последовательности. Как это отображается в DbContext? Нужно ли создавать отдельные карты для каждой СУБД?
  3. Поддерживает ли EF какой-либо механизм для обновления существующей схемы СУБД до той, которая представляет модель EF (воссоздание схемы = / = обновление), или я ограничен в выполнении этого вручную?
  4. Я придумал один из возможных способов сначала использовать базу данных и поддерживать несколько СУБД, однако это кошмар обслуживания. Идея заключалась в том, чтобы добавить еще один уровень абстракции к двум сгенерированным моделям данных и создать классы конвертера для каждой из сгенерированных моделей EF. Это кажется наилучшим способом сделать так, чтобы каждая СУБД могла иметь свою собственную модель, но мой код обрабатывал бы отображение. Но, делая это, что я действительно получаю от EF? Может быть, генерация запросов, но стоит ли это того?

Ответы [ 2 ]

2 голосов
/ 03 апреля 2011

На самом деле и модель-первая, и база-первая имеют одинаковые ограничения.Оба этих подхода используют файл EDMX, который содержит часть SSDL (описание store = уровень базы данных), связанную непосредственно с одним поставщиком базы данных, поэтому, если вы хотите иметь двух разных поставщиков базы данных, вы должны иметь две разные части SSDL и хранить их всинхронизации.Вы можете использовать один CSDL (описание концептуального уровня = классы вашей модели) и один или два MSL (описание сопоставления между SSDL и CSDL - один файл возможен, только если таблицы и столбцы будут иметь одинаковые имена в обоих SSDL).Как я знаю, файл EDMX может состоять только из отдельных частей SSDL, CSDL и MSL, поэтому я ожидаю, что у разработчика нет поддержки для этого сценария, и вам придется изменить второй SSDL вручную или использовать два EDMX = модель, каждое изменение дважды.

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

Сам EF в настоящее время не поддерживает обновление существующих БД.При использовании EDMX процесс создания базы данных контролируется либо шаблоном T4, либо рабочим процессом, так что его можно настроить, и уже есть отдельная функция, называемая Power Generation Database Pack Power Pack , которая позволяет наращивать базу данных с помощью пошагового наращивания.модель-первый подход.Проблема в том, что эта функция использует инструменты базы данных VS.Я думаю, что эти инструменты работают только с сервером SQL.Мне никогда не нравились эти автоматизированные инструменты, поэтому я все еще думаю, что обновление базы данных должно контролироваться вручную с помощью некоторых инструментов, чтобы получить скрипт разницы между текущей и последней развернутыми версиями базы данных.Скрипт diff вам нужен только при развертывании новой версии в производственной среде.В среде тестирования и разработки вы всегда можете воссоздать всю базу данных.

При работе с двумя моделями EDMX абстракция не требуется.Модели должны создавать один и тот же концептуальный слой.В таком случае вам нужен только один набор классов POCO, которые сопоставляются соглашениями (то же имя класса, что и у сущности, одинаковые свойства с одинаковыми типами и доступностью), поэтому они будут работать с обеими моделями.

Редактировать:

Основываясь на ответе @Tridus, я просто добавляю, что сначала вы можете создать базы данных и использовать fluentAPI из EF 4.1 для их отображения.Ваши базы данных должны иметь точно такую ​​же схему (имена таблиц, имена столбцов и т. Д.), Они не могут использовать какие-либо конкретные функции (я надеюсь, что последовательности не будут проблемой, потому что именно так Oracle обрабатывает столбцы с автоинкрементом).

1 голос
/ 03 апреля 2011

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

  • Последовательности едины (в том смысле, что они просто игнорируются EF). Вы можете подделать это в Oracle, поместив триггер в таблицу, которая заполняет его при вставке, но я также обнаружил, что если вам нужно обновить модель позже, то EF «забудет», что столбец является столбцом идентификаторов, и он попытается вставьте 0 в это снова. Я также нашел ненадежным в Oracle, чтобы попытаться получить новый идентификатор, если вы используете триггер. Мы просто выбрали последовательность и установили идентификатор объекта перед выполнением вставки, потому что именно так вы обычно делаете это в Oracle. Вы также можете использовать хранимую процедуру, которая ее обрабатывает.

  • Числа не обрабатываются одинаково. SQL Server использует числовые форматы, которые сопоставляются с Int32, Int64 и т. Д. Числовой формат Oracle полностью отличается, а полный диапазон Int32 в SQL Server - это число (10,0) в Oracle ... которое на самом деле является Int64 в EF, поскольку оно больше, чем Int32. Я также обнаружил, что провайдеру Oracle EF очень нравится использовать десятичную дробь, даже если в этом нет необходимости, но это, вероятно, только проблема с бета-версией.

  • Хранимые процедуры в Oracle требуют, чтобы некоторые значения были помещены в app.config / web.config для работы в EF. Я не уверен, будет ли это просто беспорядком в SQL Server или это вызовет проблемы.

Наконец, EF Code First довольно незрелый и, согласно документации, не поддерживает изменение структуры базы данных в этой версии. Я не уверен, поддерживает ли поставщик Oracle также (возможно, не пробовал).

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

edit - В отношении вашего # 4 - EF 4.1 может генерировать частичные классы POCO. Вместо того, чтобы писать обертку вокруг каждой из сгенерированных моделей, чтобы скрыть какие-либо различия, вы можете создать еще один частичный файл кода класса, который не будет регенерироваться при обновлении модели, а затем добавить свойства / методы, которые скрывают различия. Код вашего приложения должен был бы просто знать, чтобы использовать их вместо этого, и они бы справились с проблемой (например, проблема с числом, о которой я говорил, вы могли бы полностью скрыть это с другим свойством, которое может выполнить необходимое преобразование для Oracle).

...