Две ORM модели для C# и Python. Нужно решение получше
Приветствую.
Описание сложившейся ситуации ниже.
В существующем проекте, для приведения которого в порядок мы и были наняты, есть активная работа с довольно большой базой данных. Причем у компании в наличии большое количество кастомеров, соответственно каждый кастомер получает свою копию базы в момента разворачивания решения.
Процесс не организован — версионность базы не ведется, рефакторинг и нормализации базы просится уже давно, обновление баз до новой версии происходит вручную инженером.
База — MS SQL Server. Встал вопрос о применении ORM слоя и перевод многочисленных изменений баз в сферу ответственности ORM инструментария (в том числе через поддержку механизма миграций). Проект написан на C#, однако так же есть гео сервис на Python очень тесно работающий с этими же базами. Python сервис находится в стадии написания и предназначен для автоматизации ряда действий с базами. На текущий момент он юзает SQL Alchemy. Миграции не настроены.
Итак: имеем C# и Python код, которые используют одну и ту же базу. C# код работает с базой напрямую (ADO.NET), python код использует SQL Alchemy.
Для работы с базой со стороны C# кода мы также решили заюзать ORM. Выбор пал на EF 6.0, хотя это не принципиально — платные решения также рассматриваются.
Таким образом складывается не очень приятная ситуация — поддержка одновременно двух моделей. То есть, меняем таблицу — меняем обе модели сразу. Это все ничего, если бы модели были в нашем ведении, но научить другую сторону работать с python + двумя новыми ORM'ам + заставить фиксировать все изменения однвременно и сразу же в двух моделях — практически нереально. Поэтому хочу спросить сообщество, может кто сталкивался с таким вопросом и как его решили. В идеале хорошо было бы вести модель только на одном языке.
Вот какие у нас (были) идеи:
1. Просто поддерживаем две ORM модели. Вариант ввиду описанного выше не подходит
2. Наиболее продвинутая модель выполняет миграции (тут речь о C# решениях — SQL Alchemy хоть и мощная, но несколько ее решений по миграции просто не работают с SQL Server'ом), а менее просто реверсит базу и отслеживает изменения (сомневаюсь что SQL Alchemy это может)
3. Описываем модель скажем на XML а потом парсим его C# и Python парсерами и просто обновляем модели.
4. Перевод python кода на IronPython. Не получится, ибо гео сервис скорее всего просто не будет работать.
Сталкивались ли вы с нечто подобным? Какое решение использовали бы вы? Что можете посоветовать.
Нужен дополнительный слой абстакции. Скажем, берём БД+EF, пишем веб-сервисы на WebAPI, разворачиваем WebAPI. Из кода приложений на C# обращаемся по REST, из Python так же.
Хм, интересно. А можете кинуть примерчиком каким-нибудь? И что будет в WebAPI — сервисы для хранения схемы? И обработки запросов на передачу списка таблиц или хранимых процедур?
Да. Я тоже хотел предложить такой же способ. БД + EF CodeFirst с миграциями + WCF для сервисного интерфейса. Кстати, подумайте, может стоит избавиться от SQL Server и перейти на SQL Server Compact (в случае с EF CodeFirst это одна строка конфигурации), сохраняя всю базу в один файл. Передо мной сейчас практически ваша ситуация (но только без питона), и я дописываю слой работы с данными. На данный момент в проекте используется EF DatabaseFirst с кучей ALTER и CREATE на старте приложения.
Illivion, начет Compact — сомневаюсь. Баз много — для каждого кастомера — своя. Кроме того, присутствуют SDE инстансы (гео данные). Да и размер думаю не позволит в Compact положить. Хотя не знаком с ограничениями Compact.
Вы написали про WCF для сервисного интерфейса. А подробнее можете описать как бы он работал? Версионность как обеспечить? Для C# кода я например могу в DLL положить ORM модель и по версии DLL гетить нужные DDL/DML скрипты. Как в случае с WCF быть?
Вы кажется несколько не поняли затею. Сервис предоставляет интерфейс к уже более высокоуровневым операциям (типа GetClientsList, FindClientByID итд). Кстати я подумал, вам по-моему очень хорошо подойдет WCF Data Services. Это прямая реализация «БД как сервис». Вот так с ним например можно работать из браузера: WCF Data Services — Browser access
На текущий момент решение пока следующее: модель ведем в NHibernate + миграции/версионность Fluent Migrator'а. SQLAlchemy просто рефлектит текущую базу (версионность и миграции тут не нужны). Пишем модель только на C#. Однаоко, придется повтыкать с SQL Alchemy вначале.
Второй рисунок мне понятен, но учитывая специфику проекта (нет централизации БД; нет смысла в привязки C# кода к WebAPI — то есть по факту WebAPI будет только для Python) промежуточный слой только усложнит решение и увеличит код. Хотя это просто наша специфика. Решение на WebAPI я безусловно более детально изучу.
Относительно простым кажется такой вариант:
1) Все модели описывать в виде JSON-Schema
2) Написать тулзу для конвертации этой схемы в код. Не должно быть сложно.
Спасибо за ссылку. Касаемо ответа, я его первоначально невнимательно прочитал. JSON-Schema кажется действительно одним из приемлемых вариантов. Спасибо за наводку.
sqlautocode к сожалению не поддерживается. Последняя версия 0.7 и судя по некоторым постам, последняя версия не умеет работать ни с гео-таблицами, ни с индексами. Только таблицы и FK/PK.
JSON-Schema интересен, но пока не вижу как в него можно засунуть и FK и stored procedures. В виде специфичных тегов? У вас есть опыт применения JSON-Schema?
Опыт применения JSON-Schema есть, но не в таком разрезе. Есть универсальные способы описания бд в xml — типа такого propelorm.org/reference/schema.html
Дальше уже надо либо искать API для конкретных языков, либо же писать самим (что тоже на сверхзадача).
Хм. При использовании Code First Migrations для Entity Framework лезть в структуру sql вообще не надо, т.к при изменении моделей в контексте вызывается команда, которая обновляет структуру базы соответственно текущим модеям — т.е как раз версионность, и сохраняет текущую структуру ДБ у себя в коде, т.е при развертывании в чистую базу ве эти шаги миграций применяются последовательно.
Кстати, а почему вторым языком выбран питон и как ведется взаимодействие проектов?
Насчет первой части вашего ответа — да, все верно. Так и работает миграция и лезть никуда мы там и не собирались. Это комментарий или вопрос?
Касаемо второй части — Python потому что качестве back-end у нас геоинформационная система, имеющая мощные модули геопроцессинга только на Python. Проект один, просто и C# код и Python код работают с базой. А на сервис геопроцесинга вешается бринг-ап базы данных с предвариательным геопроцессингом данных.
программист, python, django, mysql, git, hg, linux
Я бы остановился на 2-м варианте. Сложность конечно в том, что если два разных VCS-репозитория то замучаетесь с синхронизацией веток... Парсеры JSON/XML/etc описаний модели - еще один контур отказа как минимум, как максимум - затратный по человекочасам на разработку/поддержку.
Еще совет: подключите администрацию и "прогните" ту сторону :)