Pull to refresh

Автоматизация изменений БД в .NET

Reading time 5 min
Views 5.8K
Здравствуйте!
Я хотел бы рассказать о проектах Migrator.Net и ECM7.Migrator.

Migrator.Net — это механизм контроля версий базы данных, похожий на Migrations в Ruby on Rails. Migrator позволяет автоматизировать выполнение операций изменения БД и автоматически ведет учет версий.

Migrator написан на C# и будет удобен, в первую очередь, при использовании в проектах под.NET.

Сначала я сделаю небольшой обзор указанных проектов, а потом постараюсь выделить их «плюсы» и «минусы».



Основные принципы

Для изменения БД вы создаете сборку, содержащую «миграции». «Миграции» — это классы, каждый из которых описывает небольшое изменение БД.

При написании классов-«миграций» необходимо унаследоваться от специального базового класса Migration и перекрыть 2 метода:
  • метод Up задает операции над БД, необходимые для перехода к следующей версии БД (например, создание таблицы);
  • метод Down задает операции, необходимые для отмены изменений, выполненных методом Up (например, если в методе Up создается новая таблица, то в методе Down она должна удаляться).


Действия, которые необходимо выполнить над БД, задаются на том языке, на котором вы пишете ваш .NET проект. Имеется специальный framework, содержащий классы и методы для выполнения основных операций над БД. Также есть возможность выполнить произвольный SQL-запрос.

Пример миграции

[Migration(7)]
public class AbstractTestMigration : Migration
{
    override public void Up()
    {
      Database.AddTable("CustomerAddress",
        new Column("customer_id",
            DbType.Int32, ColumnProperty.PrimaryKey),
        
        new Column("address",
            DbType.AnsiString, ColumnProperty.NotNull));
    }

    override public void Down()
    {
      Database.RemoveTable("CustomerAddress");
    }
}

* This source code was highlighted with Source Code Highlighter.


Давайте разберем, что тут происходит:
  1. Мы видим, что наш класс-«миграция» помечен атрибутом [Migration(7)]. Параметр атрибута — значение типа long, задающее номер версии БД, на который произойдет переход при выполнении изменений из метода Up.
  2. Как мы уже говорили, класс-«миграция» должен быть унаследован от базового класса Migration. Также класс-«миграция» должен переопределять методы Up и Down базовго класса.
  3. Базовый класс Migration имеет свойство Database. Это свойство содержит объект, реализующий интерфейс ITransformationProvider. Вызывая методы интерфейса ITransformationProvider у объекта Database можно выполнять операции над БД. Например, в методе Down используется Database.RemoveTable для удаления таблицы.
    Интерфейс ITransformationProvider содержит метод int ExecuteNonQuery(string sql), позволяющий выполнить произвольный SQL-запрос.

Способы выполнения изменений

Migrator предоставляет несколько способов запуска на выполнение ваших классов-«миграций».
  1. Консольное приложение
  2. Task для NAnt
  3. Task для MsBuild
  4. Программное выполнение — выполнение «миграций» из вашей программы через API

Каждый из этих способов получает в качестве параметров тип используемой СУБД, строку подключения и номер версии БД, которую необходимо получить.


Поддерживаемые СУБД

Migrator.NET может работать с различными СУБД. При запуске «миграций» на выполнение вместе с параметрами подключения к БД мигратору указывается класс-«диалект», при помощи которого формируются SQL-запросы для конкретной СУБД.

В проекте Migrator.NET есть «диалекты» для следующих СУБД: MySQL, Oracle, SQLite, MS SQL Server (в т.ч. CE), PostgreSQL.

Отличия проектов Migrator.Net и ECM7.Migrator

В начале этого поста я упомянул вместе с Migrator.Net еще один проект: ECM7.Migrator. Сейчас я расскажу о нем подробнее.

Весной этого года мы с коллегами узнали про Migrator.NET. Мы попробовали его использовать и нам очень понравилось. Сейчас я использую мигратор на обеих моих работах (в сумме 3 довольно больших проекта, уже работающих в реальных условиях).
К сожалению, оказалось, что Migrator.NET имеет некоторые неудобства, а также его провайдер для Oracle содержит много ошибок (об этом, кстати, написано на главной странице проекта в google code).

За период с мая по сентябрь в Migrator.NET нами было внесено большое количество изменений: переписано несколько классов т.н. «ядра», исправлено много ошибок в оракловом провайдере, несколько «косметических» доработок, делающих использование мигратора более удобным.

В результате, код, который мы дорабатывали настолько разошелся с кодом оригинального проекта, что решено было сделать отдельный проект. Именно он и выложен в google code под названием ECM7.Migrator. Также была частично переведена (и исправлена под новый проект) документация.

Кроме того, за ненадобностью была удалена поддержка PostgreSQL.

Чем мигратор может вам помочь

  1. С мигратором изменения БД удобно распространять. Нет папки с кучей скриптов, вместо нее единственная dll. Думаю, вы оцените это, если вам нужно будет обновить windows-приложение у нескольких сотен пользователей.
  2. Миграции удобно писать: проверка на этапе компиляции, intellisense и т.д. Никто не пишет SQL вручную. Обычно его генерируют через GUI. Часто при этом генерируется куча «левых» команд. С мигратором вы можете полностью все контролировать, не затрачивая на это много времени.
  3. Миграции удобно выполнять. Как я уже писал, для мигратора имеются таски для NAnt и MSBuild. С ними вы легко сможете выполнять миграции во время автоматизированной сборки вашего проекта. Кроме того, средства программного выполнения миграций делают возможными такие вещи как обновление структуры БД при старте приложения или создание чистой БД для модульных тестов.
  4. Миграции не зависят от СУБД. Если честно, мне ни разу еще не приходилось работать над проектом, который должен поддерживать несколько СУБД. Но, возможно, независимость от СУБД тоже кому-то нужна.
  5. В миграции легко добавлять произвольную логику. Например, вы можете в цикле создать кучу таблиц или добавить к названию каждой таблицы некоторый префикс, определяемый в настройках приложения.

Недостатки

За время моей работы с мигратором я почувствовал два его недостатка:
  1. Если человек не любит работать с программами через командную строку (как и я), то для него будет недостатком отсутствие программы с GUI, позволяющей запустить миграции на выполнение. К счастью, эта проблема быстро решилась написанием bat — файла, запускающего консольное приложение мигратора с нужными параметрами.
  2. Второе неудобство заключается в том, что когда я пишу миграцию, я не помню названия уже созданных объектов БД. Эту проблему так и не удалось устранить. При написании миграций смотрю названия в GUI или в файлах hbm (у нас во многих проектах используется NHibernate).


Чего не может мигратор

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

Заключение

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

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

Всем спасибо за внимание.

— Примечание
Некоторое время назад здесь уже обсуждался проект octalforty Wizardby. Насколько я понял, это еще один мигратор.
К сожалению, очень кратко ознакомился с данным проектом. Основное отличие, которое бросается в глаза — там «миграции» пишутся на специальном языке.
Если вы использовали Wizardby в реальных условиях, напишите мне. Было бы очень интересно узнать о его достоинствах/недостатках и сравнить его с Migrator.NET.
Tags:
Hubs:
+26
Comments 46
Comments Comments 46

Articles