Pull to refresh

Миграции БД для .NET

Reading time 3 min
Views 7K
В и без того непростом процессе разработки программных продуктов время от времени появляются совсем уж неприятные вопросы. Один из них — что же делать со структурой БД, как хранить информацию о версиях, как обновлять копии БД на серверах да и как организовывать совместную работу.


Проблема


База данных — это неотъемлемая часть вашего приложения. Если развернуть версию 2.0 этого самого приложения на базе данных версии 1.0, то, в общем случае, в итоге получится неработоспособная программа. Именно поэтому БД должна находится в системе контроля версий непосредственно рядом с исходниками программы.

Вся соль проблемы заключается в том, что условие «непосредственно рядом» в случае с БД довольно непросто выполнить. Встает вопрос о том, что именно хранить в системе контроля версий. Всю БД? Совершенно бессмысленное занятие. Всю заскриптованную схему БД? Как тогда делать инкрементальные изменения существующих структур? Скрипты с инкрементальными изменениями? Очевидно, это и будет самым правильным решением, однако же как удостовериться в том, что скрипты применяются в правильной последовательности, ровно столько раз, сколько требуется, и ровно на тех базах данных, на которых это необходимо?

Решение


Вот в этот момент на сцену выходят специальные средства.

Одно из них (начинается бессовестный пиар, ради которого все и затевалось) — octalforty Wizardby. Этот инструмент позволяет автоматизировать доведение схемы БД «до кондиции», сводя все необходимые манипуляции к двум вещам: написанию миграций и работе с консольным приложением, обрабатывающим упомянутые миграции.

По сути, «миграция» — это инструкция, говорящая о том, как из схемы БД версии N сделать схему версии N + 1. Другими (совсем другими) словами:

migration "Oxite" revision => 1:  <br>    version 20090323103239:<br>        add table oxite_Language:<br>            add column LanguageID type => Guid, nullable => false, primary-key => true<br>            add column LanguageName type => AnsiString, length => 8, nullable => false<br>            add column LanguageDisplayName type => String, length => 50, nullable => false<br><br>* This source code was highlighted with Source Code Highlighter.


и далее:



то в итоге:



А вот если потом:

    version 20090330170528:<br>        oxite_User:<br>            UserID type => PK, primary-key => true<br>            Username type => LongName, unique => true<br>            DisplayName type => LongName<br>            Email type => LongName<br>            HashedEmail type => ShortName<br>            Password type => MediumName<br>            PasswordSalt type => MediumName<br>            DefaultLanguageID references => oxite_Language<br>            Status type => Byte, nullable => false<br>            <br>        oxite_UserLanguage:<br>            UserID references => oxite_User<br>            LanguageID references => oxite_Language<br><br>            index "" columns => [UserID, LanguageID], unique => true, clustered => true<br><br>* This source code was highlighted with Source Code Highlighter.


то Wizardby все равно все сделает самостоятельно:


Проект


Страница проекта (лицензированного под MIT License) находится здесь. Исходный код доступен либо в виде ZIP-архива, либо в SVN репозитории. Кроме того, есть ZIP-архив с уже скомпилированной версией. Документация же (на английском) — тут. А здесь можно посмотреть, как Wizardby используется в «реальной жизни».
Tags:
Hubs:
+12
Comments 46
Comments Comments 46

Articles