Нужен совет по объединению ORM и SQL с устаревшей системой - PullRequest
2 голосов
/ 16 ноября 2008

Мы находимся в процессе переноса устаревшей системы на .NET, как для очистки архитектуры, так и для использования множества новых возможностей, которые просто нелегко реализовать в устаревшей системе.

Примечание. Читая мой пост перед его отправкой, я замечаю, что, возможно, в некоторых местах я описывал слишком быстро, т.е. затмил детали. Если есть что-то непонятное, оставьте комментарий (не ответ), и я увеличу как можно больше

Устаревшая система использует базу данных и 100% пользовательский написанный SQL повсюду. Это привело к появлению широких таблиц (т. Е. Множества столбцов), поскольку код, которому нужны данные, извлекает только то, что необходимо для работы.

В качестве части порта мы добавили слой ORM, который мы можем использовать в дополнение к пользовательскому SQL. ORM, который мы выбрали, это DevExpress XPO, и одна из функций этого также привела к некоторым проблемам для нас, а именно: когда мы определяем класс ORM для, скажем, таблицы Employee, мы должны добавить свойства для всех столбцов, в противном случае он не получит их для нас.

Это также означает, что когда мы получаем сотрудника, мы получаем все столбцы, даже если нам нужно только несколько.

Хорошая особенность использования ORM состоит в том, что мы можем поместить некоторую логику, связанную со свойствами, в одни и те же классы, не дублируя ее повсюду. Например, простое выражение для объединения имени, отчества и фамилии в «отображаемое имя» может быть помещено в качестве примера.

Однако, если мы пишем код SQL где-либо, либо в DAL-подобной конструкции, либо, ну, везде, нам нужно дублировать это выражение. Это неправильно и похоже на рецепт ошибок и кошмара обслуживания.

Однако, поскольку у нас есть два варианта:

  • ORM, выбирает все, логика может быть записана один раз
  • SQL, выбирает то, что нам нужно, нужно продублировать логику

Тогда мы придумали альтернативу. Поскольку объекты ORM генерируются кодом из словаря, мы решили также создать набор тупых классов. Они будут иметь одинаковое количество свойств, но не будут одинаково связаны с ORM. Кроме того, мы добавили интерфейсы для всех объектов, также сгенерированных, и заставили и ORM, и объекты dum реализовать этот интерфейс.

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

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

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

Это также выглядит неуклюже для нас.

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

В настоящее время мы не можем разбивать таблицы. Устаревшее приложение все еще будет существовать в течение нескольких лет из-за размера порта, и код .NET не является проектом типа выпуска в течение 3 лет, но будет постепенно внедряться в выпуски. Таким образом, и устаревшая система, и код .NET должны работать с одними и теми же таблицами.

Мы также знаем, что это не идеальное решение, поэтому, пожалуйста, воздержитесь от совета типа «Вы не должны были делать это так». Нам это хорошо известно:)


Одна вещь, которую мы рассмотрели, - это создание файла XML или аналогичного с «контрактами». Таким образом, мы можем поместить в этот XML-файл что-то вроде этого:

  • Существует класс Employee с этими 50 свойствами
  • Кроме того, у нас есть эти 7 вариантов для различных частей программы
  • Кроме того, у нас есть эти 10 частей логики, для каждого из которых требуются свойства X, Y и Z (X, Y и Z варьируются между этими 10)

Это может позволить нам сгенерировать код этих 8 классов (полный класс + 7 меньших вариаций) и заставить генератор обнаружить, что для варианта № 3 присутствуют свойства X, Y и K, и я могу затем связать код для логики или интерфейсы, в которых логика нуждается в этом классе автоматически. Это позволило бы нам иметь несколько различных типов классов сотрудников с различной степенью охвата свойств и иметь генератор, автоматически добавляющий в него всю логику, которая будет поддерживаться этим классом.

Мой код может сказать, что мне нужен сотрудник типа IEmployeeWithAddressAndPhoneNumbers.

Это тоже выглядит неуклюже.

Ответы [ 3 ]

3 голосов
/ 16 ноября 2008

Я бы предположил, что в конечном итоге рефакторинг базы данных (нормализация), вероятно, в порядке. Вы можете работать над рефакторингом и использовать представления, чтобы предоставить устаревшему приложению интерфейс с базой данных в соответствии с тем, что оно ожидает. То есть, например, разбейте таблицу сотрудников на employee_info, employee_contact_info, employee_assignments, а затем предоставьте устаревшему приложению представление с именем employee, которое объединяет эти три таблицы (или, возможно, табличную функцию, если логика более сложный). Это потенциально позволит вам продвинуться вперед с помощью полностью ORM-решения, которое я бы предпочел, и порадовать ваше старое приложение. Я бы не стал использовать смешанное решение ORM / прямой SQL, хотя вы могли бы расширить свой ORM, имея несколько классов сущностей, которые предоставляют разные представления одних и тех же данных (например, объединение нескольких таблиц для отображения только для чтения). ).

2 голосов
/ 16 ноября 2008

"В настоящее время мы не можем разбивать таблицы. Устаревшее приложение все равно будет существовать в течение ряда лет из-за размера порта, а код .NET не является ин-3 -years-release тип проекта, но будет постепенно внедряться в выпуски в дальнейшем. Таким образом, и устаревшая система, и код .NET должны работать с одними и теми же таблицами. "

Два слова: материализованные взгляды.

У вас есть несколько способов «нормализации на месте».

  1. Материализованные представления, / k / a индексированные представления. Это нормализованный клон исходных таблиц.

  2. Явное копирование из старых таблиц в новые таблицы. «Крик», говорите вы. Однако учтите, что вы постепенно удаляете функциональность из старого приложения. Это означает, что у вас будут некоторые функциональные возможности в новых, нормализованных таблицах, а старые таблицы можно изящно игнорировать.

  3. Явная двусторонняя синхронизация. Это сложно, не невозможно. Вы нормализуетесь путем копирования из ваших прежних таблиц в правильно разработанные таблицы. В качестве временного решения вы можете использовать хранимые процедуры и триггеры для клонирования транзакций в устаревшие таблицы. Затем вы можете удалить эти кладжи, когда ваше преобразование будет продолжено.

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

0 голосов
/ 16 ноября 2008

Хотя я не использовал этот конкретный ORM, в некоторых случаях представления могут быть полезны для предоставления более легких объектов для отображения и создания отчетов в этих типах баз данных. Согласно их документации они поддерживают такую ​​концепцию: XPView Concepts

...