Миграции в framework выполняются транзакционно или нет

Обновлено: 07.07.2024

Миграция данных - это операция миграции таблицы базы данных, достигающая синхронизации информации между командой, и данные едины.

Миграция базы данных

1. В миграции Yii2 часто используется для изменения таблицы данных базы данных, в основном для эксплуатации структуры и небольших частичных данных (редко встречающихся большие данные, если это относительно большое количество данных, используя данные прямого экспорта таблицы ).

2, локально генерируют или измените таблицу базы данных, оператор выполнения Backend: ./yii миграция / создание <create_table_name>

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

4. Другие участники возвращают его к последнему коду обратно на локальный, выполните ./yii Migrate Обновите состояние миграции данных и синхронизируйте последнюю миграцию данных в локальный.

концепция

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

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

Следующие шаги показывают нам, как используется инструмент миграции базы данных для команды разработки:

Тим создает новый объект миграции (например, создать новую форму, изменяя определение поля и т. Д.).

Тим отправляет этот новый объект миграции к системе управления кодом (например, Git, Mercurial).

Даг обновляется из системы управления кодами и получает этот новый объект миграции.

Даг представил этот объект миграции в местную базу данных развития, чтобы Даг синхронизировал модификацию Тим.

Следующие шаги показывают нам, как выпустить новую версию миграции базы данных в производственную среду:

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

SCOTT обновляет исходный код опубликованного ярлыка на сервер производственной среды.

SCOTT представляет всю инкрементную базу данных в базу данных производственной среды.

Yii предоставляет полный набор инструментов командной строки миграции, вы можете:

Создать новую миграцию (./yii Migrate / создание описания миграции);

Реалистичная история миграции и статус.

Все эти инструменты могут управляться команмами Yii Migrate.
Примечание. Миграция не только на таблице базы данных, но также настраивает существующие данные для размещения новых форм, создают слои RBAC или Clear Cache.

Создать миграцию

Используйте следующую команду для создания новой миграции:

Функция необходимого имени параметра является краткое описание новой миграции.

Например, если эта миграция используется для создания формы под названием News, вы можете использовать имя_News_Table и выполнить следующую команду:

ПРИМЕЧАНИЕ. Поскольку параметр имени используется для генерации части имени класса миграции, этот параметр должен содержать только буквы, номера и подчеркивание.

Если приведенная выше команда создаст новый файл класса PHP, называемый M150101_185401_CREATE_NEWS_TABLE.PHP в каталоге @ app / Migrations.

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

Каждая миграция базы данных будет определена как класс PHP, унаследованный от YiidBMigration. Имя класса автоматически генерируется в соответствии с форматом m <yymmdd_hmmms> _ <name>, где

<YYMMDD_HHMMMS> относится к времени UTC для создания команды миграции.

<Имя> совпадает с ремнем значения параметра имени при выполнении команды.

В классе миграции вы должны написать код, который меняет структуру базы данных в методе UP (). Вам также может потребоваться записать код в методе down () для восстановления изменений, сделанных методом UP ().

Когда вы обновляете базу данных через миграцию, будет вызываться метод UP (), но будет вызываться обратный, вниз (). Следующий код показывает, как создать новостную таблицу путем миграционных классов:

Примечание: не все миграции извлекаются.

Например, если метод UP () удаляет строку данных в таблице, это не сможет восстановить эти данные через метод down (). Иногда вы можете просто быть лень, чтобы выполнить метод down (), потому что он не так распространен в миграции базы данных восстановления. В этом случае вы должны вернуть ложь в методе down (), чтобы указать, что эта миграция не может быть восстановлена.

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

Эта команда покажет все неблагоприятные миграции.

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

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

Совет: инструмент миграции автоматически создает таблицу миграции в базе данных, которая указана в опции yicontroller . db в команде. По умолчанию он указывается компонентом приложения БД.

Вы также можете указать конкретную миграцию, используйте migrate / to command в следующем формате, чтобы указать, какая миграция должна быть представлена:

Если не представлена ​​миграция перед передачей миграции, эта пропавшая миграция будет представлена ​​в первую очередь до выполнения этой заданной миграции.

Если миграция указанного представления ранее представлена, то эти миграции после этого будут восстановлены.

Восстановление миграции

Вы можете использовать следующую команду для восстановления одного или нескольких мнения, представленных миграцией:

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

Примечание. Если миграция не может быть восстановлена, то вы не сможете это сделать.

Перечислите миграцию

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

Изменить историю миграции

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

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

Ни одна миграция не будет представлена ​​или восстановлена ​​во время этой команды.

Глобальная команда конфигурации

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

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

Миграция нескольких баз данных

Вышеуказанная команда представит миграцию в базу данных DB2.

Изредка вам необходимо представить некоторую миграцию в базу данных, в то время как другие представлены в другую базу данных. Чтобы добиться этого, вы должны указать идентификатор компонента баз данных, который вам необходимо использовать, когда вы реализуете класс миграции, как показано ниже:

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

Если есть несколько миграций для использования одной базы данных, рекомендуется создать мигрированный базовый класс, который содержит код выше INIT (). Затем каждый класс миграции наследует этот базовый класс.

Совет: В дополнение к настройкам в параметре YiidBmigration :: :: :: :: :: :: db, вы также можете управлять разными базами данных, создавая новые соединения баз данных в классе миграции. Затем метод DAO используется для эксплуатации различных баз данных с этими соединениями.

Другая политика, которая позволяет перенести несколько баз данных, чтобы перенести миграцию в разные каталоги, то вы можете перенести разные базы данных по следующим командам:

Первая команда представит миграцию в каталоге @ App / Migrations / DB1 в базу данных DB1, а вторая команда будет представить миграцию в App / Migrations / DB2 в базу данных DB2 и так далее.

В ходе разработки и ведения баз данных приложений, которые управляют данными, структуры используемых баз данных развиваются как и исходный код приложений. Например, при разработке приложения, в будущем может оказаться необходимой новая таблица; уже после того, как приложение будет развернуто в рабочем режиме (продакшене), также может быть обнаружено, что для повышения производительности запросов должен быть создан определённый индекс; и так далее. В связи с тем, что изменение структуры базы данных часто требует изменение исходного кода, yii поддерживает так называемую возможность миграции баз данных, которая позволяет отслеживать изменения в базах данных при помощи терминов миграции баз данных, которые являются системой контроля версий вместе с исходным кодом.

Следующие шаги показывают, как миграции базы данных могут быть использованы командой разработчиков в процессе разработки:

  1. Илья создает новую миграцию (например, создается новая таблица или изменяется определение столбца и т.п.).
  2. Илья фиксирует новую миграцию в системе управления версиями (например, в Git, Mercurial).
  3. Алексей обновляет свой репозиторий из системы контроля версий и получает новую миграцию.
  4. Алексей применяет миграцию к своей локальной базе данных, тем самым синхронизируя свою базу данных, для того чтобы отразить изменения, которые сделал Илья.

А следующие шаги показывают, как развернуть новый релиз с миграциями баз данных в рабочем режиме (продакшена):

  1. Сергей создаёт новую версию проекта репозитория, которая содержит некоторые новые миграции баз данных.
  2. Сергей обновляет исходный код на рабочем сервере до новой версии.
  3. Сергей применяет любую из накопленных миграций баз данных в рабочую базу данных.

Yii предоставляет набор инструментов для миграций из командной строки, которые позволяют:

  • создавать новые миграции;
  • применять миграции;
  • отменять миграции;
  • применять миграции повторно;
  • показывать историю и статус миграций;

Все эти инструменты доступны через команду yii migrate . В этом разделе мы опишем подробно, как выполнять различные задачи, используя эти инструменты. Вы также можете сами посмотреть как использовать каждый отдельный инструмент при помощи команды yii help migrate .

Создание миграций

Чтобы создать новую миграцию, выполните следующую команду:

Требуемый аргумент name даёт краткое описание новой миграции. Например, если миграция о создании новой таблицы с именем news, Вы можете использовать имя create_news_table и выполнить следующую команду:

Примечание: Поскольку аргумент name будет использован как часть имени класса создаваемой миграции, он должен содержать только буквы, цифры и/или символы подчеркивания.

Приведенная выше команда создаст новый PHP класс с именем файла m150101_185401_create_news_table.php в директории @app/migrations . Файл содержит следующий код, который главным образом декларирует класс миграции m150101_185401_create_news_table с следующим каркасом кода:

Каждая миграция базы данных определяется как PHP класс расширяющийся от [[yii\db\Migration]]. Имя класса миграции автоматически создается в формате m<YYMMDD_HHMMSS>_<Name> ( m<ГодМесяцДень_ЧасыМинутыСекунды>_<Имя> ), где

  • <YYMMDD_HHMMSS> относится к UTC дате-времени при котором команда создания миграции была выполнена.
  • <Name> это тоже самое значение аргумента name которое вы прописываете в команду.

В классе миграции, Вы должны прописать код в методе up() когда делаете изменения в структуре базы данных. Вы также можете написать код в методе down() , чтобы отменить сделанные up() изменения. Метод up вызывается для обновления базы данных с помощью данной миграции, а метод down() вызывается для отката изменений базы данных. Следующий код показывает как можно реализовать класс миграции, чтобы создать таблицу news :

Для справки: Не все миграции являются обратимыми. Например, если метод up() удаляет строку из таблицы, возможно что у вас уже не будет возможности вернуть эту строку методом down() . Иногда Вам может быть просто слишком лень реализовывать метод down() , в связи с тем, что это не очень распространено - откатывать миграции базы данных. В этом случае вы должны в методе down() вернуть false , чтобы указать, что миграция не является обратимой.

Базовый класс миграций [[yii\db\Migration]] предоставляет подключение к базе данных через свойство [[yii\db\Migration::db|db]]. Вы можете использовать его для манипулирования схемой базы данных используя методы описанные в работе со схемой базы данных.

Вместо использования физических типов данных, при создании таблицы или столбца, следует использовать абстрактные типы для того, чтобы ваша миграция являлась независимой от конкретной СУБД. Класс [[yii\db\Schema]] определяет набор констант для предоставления поддержки абстрактных типов. Эти константы называются в следующем формате TYPE_<Name> . Например, TYPE_PK относится к типу автоинкремента (AUTO_INCREMENT) первичного ключа; TYPE_STRING относится к строковому типу. Когда миграция применяется к конкретной базе данных, абстрактные типы будут переведены в соответствующие физические типы. В случае с MySQL, TYPE_PK будет превращено в int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY , а TYPE_STRING станет varchar(255) .

Вы можете добавить дополнительные ограничения при использовании абстрактных типов. В приведенном выше примере, NOT NULL добавляется к Schema::TYPE_STRING чтобы указать, что столбец не может быть NULL.

Для справки: Сопоставление абстрактных типов и физических типов определяется свойством [[yii\db\QueryBuilder::$typeMap|$typeMap]] в каждом конкретном QueryBuilder классе.

Транзакции Миграций

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

Самый простой способ реализации транзакций миграций это прописать код миграций в методы safeUp() и safeDown() . Эти два метода отличаются от методов up() и down() тем, что они неявно заключены в транзакции. В результате, если какая-либо операция в этих методах не удается, все предыдущие операции будут отменены автоматически.

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

Обратите внимание, что обычно при выполнении нескольких операций в базе данных при помощи метода safeUp() , вы должны реализовать обратный порядок исполнения в методе safeDown() . В приведенном выше примере мы сначала создали таблицу, а затем вставили строку в safeUp() ; а в safeDown() мы сначала удаляем строку и затем удаляем таблицу.

Примечание: Не все СУБД поддерживают транзакции. И некоторые запросы к базам данных не могут быть введены в транзакции. Для различных примеров, пожалуйста, обратитесь к негласным обязательствам. В этом случае вместо этих методов вы должны реализовать методы up() и down() .

Методы доступа к базе данных

Базовый класс миграции [[yii\db\Migration]] предоставляет набор методов, которые позволяют Вам получить доступ и управлять базами данных. Вы можете найти эти методы, их названия аналогичны методам DAO, предоставленным в классе [[yii\db\Command]]. Например, метод [[yii\db\Migration::createTable()]] позволяет создать новую таблицу, подобно методу [[yii\db\Command::createTable()]].

Ниже представлен список всех этих методов доступа к базам данных:

  • [[yii\db\Migration::execute()|execute()]]: выполнение SQL инструкции
  • [[yii\db\Migration::insert()|insert()]]: вставка одной строки
  • [[yii\db\Migration::batchInsert()|batchInsert()]]: вставка нескольких строк
  • [[yii\db\Migration::update()|update()]]: обновление строк
  • [[yii\db\Migration::delete()|delete()]]: удаление строк
  • [[yii\db\Migration::createTable()|createTable()]]: создание таблицы
  • [[yii\db\Migration::renameTable()|renameTable()]]: переименование таблицы
  • [[yii\db\Migration::dropTable()|dropTable()]]: удаление таблицы
  • [[yii\db\Migration::truncateTable()|truncateTable()]]: удаление всех строк в таблице
  • [[yii\db\Migration::addColumn()|addColumn()]]: добавление столбца
  • [[yii\db\Migration::renameColumn()|renameColumn()]]: переименование столбца
  • [[yii\db\Migration::dropColumn()|dropColumn()]]: удаление столбца
  • [[yii\db\Migration::alterColumn()|alterColumn()]]: изменения столбца
  • [[yii\db\Migration::addPrimaryKey()|addPrimaryKey()]]: добавление первичного ключа
  • [[yii\db\Migration::dropPrimaryKey()|dropPrimaryKey()]]: удаление первичного ключа
  • [[yii\db\Migration::addForeignKey()|addForeignKey()]]: добавление внешнего ключа
  • [[yii\db\Migration::dropForeignKey()|dropForeignKey()]]: удаление внешнего ключа
  • [[yii\db\Migration::createIndex()|createIndex()]]: создание индекса
  • [[yii\db\Migration::dropIndex()|dropIndex()]]: удаление индекса

Применение Миграций

Для обновления базы данных до последней структуры, Вы должны применить все новые миграции, используя следующую команду:

Эта команда выведет список всех миграций, которые не применялись до сих пор. Если Вы подтвердите, что Вы хотите применить эти миграций, то этим самым запустите метод up() или safeUp() в каждом новом классе миграции, один за другим, в порядке их временного значения timestamp.

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

Примечание: Инструмент миграции автоматически создаст таблицу migration в базе данных указанной в параметре [[yii\console\controllers\MigrateController::db|db]]. По умолчанию база данных определяется как компонент приложения db .

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

Также можно явно указать конкретную миграцию, которая должна быть применена к базе данных, это можно сделать при помощи команды migrate/to в одном из следующих форматов:

Если раньше имелись какие-либо не применённые миграции, до указанной конкретной миграции, то все они будут применены до данной миграции. А если указанная миграция уже применялась ранее, то любые более поздние версии данной прикладной миграции будут отменены.

Отмена Миграций

Чтобы отменить (откатить) одну или несколько миграций, которые применялись ранее, нужно запустить следующую команду:

Примечание: Не все миграции являются обратимыми. При попытке отката таких миграций произойдёт ошибка и остановится весь процесс отката.

Перезагрузка Миграций

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

Примечание: Если миграция не является обратимой, Вы не сможете её перезагрузить.

Список Миграций

Чтобы посмотреть какие миграции были применены, а какие нет, используйте следующие команды:

Изменение Истории Миграций

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

Эта команда изменит таблицу migration добавив или удалив определенные строки, тем самым указав, что к базе данных была применена указанная миграция. Никаких миграций не будет применяться или отменяться по этой команде.

Настройка Миграций

Есть несколько способов настроить команду миграции.

Используя Параметры Командной Строки

В команду миграций входит несколько параметров командной строки, которые могут использоваться, для того, чтобы настроить поведение миграции:

interactive : логический тип - boolean (по умолчанию true). Указывает, следует ли выполнять миграцию в интерактивном режиме. Если это значение является - true, то пользователю будет выдан запрос, перед выполнением командой определенных действий. Вы можете установить это значение в false если команда используется в фоновом режиме.

migrationPath : строка - string (по умолчанию @app/migrations ). Указывает каталог для хранения всех файлов классов миграций. Этот параметр может быть определён либо как путь до директории, либо как псевдоним пути. Обратите внимание, что данный каталог должен существовать, иначе команда будет выдавать ошибку.

migrationTable : строка - string (по умолчанию migration ). Определяет имя таблицы в базе данных в которой хранится информация о истории миграций. Эта таблица будет автоматически создана командой миграции, если её не существует. Вы также можете создать её вручную, используя структуру version varchar(255) primary key, apply_time integer .

db : строка - string (по умолчанию db ). Определяет ID базы данных компонента приложения. Этот параметр представляет собой базу данных, которая подвергается миграциям при помощи команды миграций.

templateFile : строка - string (по умолчанию @yii/views/migration.php ). Указывает путь до файла шаблона, который используется для формирования скелета класса файлов миграции. Этот параметр может быть определён либо как путь до файла, либо как псевдоним пути. Файл шаблона - это PHP скрипт, в котором можно использовать предопределенную переменную с именем $className для того, чтобы получить имя класса миграции.

В следующем примере показано, как можно использовать эти параметры.

Например, если мы хотим перенести модуль forum , чьи файлы миграций расположены в каталоге migrations данного модуля, для этого мы можем использовать следующую команду:

Глобальная Настройка Команд

Вместо того, чтобы каждый раз вводить одинаковые значения параметров миграции, когда вы запускаете команду миграции, можно настроить её раз и навсегда в конфигурации приложения, как показано ниже:

С приведённой выше конфигурацией, каждый раз при запуске команды миграции, таблица backend_migration будет использована для записи истории миграций. И Вам больше не нужно указывать её через параметр migrationTable в командной строке.

Миграции в Несколько Баз Данных

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

Приведенная выше команда применит миграции к базе данных db2 .

Иногда может случиться так, что Вы захотите применить некоторые из миграций к одной базе данных, а некоторые другие к другой базе данных. Для достижения этой цели, при реализации класса миграции, необходимо явно указать идентификатор ID компонента базы данных, который миграция будет использовать, следующим образом:

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

Если у вас есть несколько миграций, которые используют ту же другую базу данных, то рекомендуется создать базовый класс миграций выше кода init() . Затем каждый класс миграции может расширяться от этого базового класса.

Совет: Кроме установки свойства [[yii\db\Migration::db|db]], Вы также можете работать с разными базами данных путем создания нового соединения с конкретной базой данных в классе Вашей миграции. Можно использовать DAO методы с этими соединениями для манипулирования различными базами данных.

Другая стратегия, которую Вы можете выбрать, чтобы перенести (мигрировать) несколько баз данных - это сохранить миграции различных баз данных в разные директории. Затем вы можете перенести эти базы данных в нужные базы следующими командами:

Первая команда применит миграции в директории @app/migrations/db1 к базе данных db1 , а вторая команда применит миграции в директории @app/migrations/db2 к базе данных db2 и так далее.

Миграции являются удобным инструментом для изменения структуры базы данных и поддержания ее в актуальном состоянии.

Yii2 поддерживает миграции из коробки. Использование миграций подробно описано в документации. Управление миграциями осуществляется из командной строки.

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

К сожалению, готового решения не нашел, поэтому заглянем в код фреймворка и посмотрим, как работают миграции.

Команда yii migrate использует yii\console\controllers\MigrateController

Для создания новой миграции используется шаблон migration.php

Все миграции наследуются от yii\db\Migration.

1. Для начала переопределяем базовый класс миграции для каждой БД. В папке components создаем классы CustomMigrationDb и CustomMigrationDb2

CustomMigrationDb2.php


2. В папке \views\migrations создаем файлы migration_db.php и migration_db2.php — шаблоны для новых миграций. Достаточно скопировать базовый шаблон и поменять базовый класс на те, что мы только что создали.

migration_db2.php

3. Теперь создаем контроллеры. В папке commands создаем классы MigrateDbController и MigrateDb2Controller. Наследуем их от yii\console\controller\MigrateController.

MigrateDb2Controller.php


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

4. Отключаем стандартный yii migrate, вместо него будем использовать один из созданных контроллеров. Для этого добавим в файл \config\console.php следующий код:

UPD: zvirusz предлагает все контроллеры миграций вынести в controllerMap. Для этого нужно добавить в \config\console.php такой код.

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

yii migrate-db
yii migrate-db2

Работают как обычные миграции. Новые миграции создаются в отдельных папках для каждой бд командами

yii migrate-db/create и
yii migrate-db2/create

Написал небольшое приложение для демонстрации. Выложил на github.
Спасибо за внимание.


Использование миграции - это стандартный способ создания и обновления базы данных с помощью Entity Framework Core. Процесс миграции состоит из двух этапов: создание миграции и применение миграции. Как мы уже говорили, схема нашей базы данных должна быть согласована с моделью базы данных, и каждое изменение в модели базы данных необходимо переносить в саму базу данных.

Эти изменения могут быть, например, следующими:

  • Изменения в свойствах класса модели
  • Изменения конфигурации
  • Добавление или удаление свойств DbSet<T> из класса контекста

Чтобы создать миграцию, мы можем использовать окно консоли диспетчера пакетов Visual Studio или командное окно (командная строка Windows) :

Добавление миграции Add-Migration MigrationName [options]

Или через интерфейс командной строки dotnet:

dotnet ef migrations добавить MigrationName [options]

В нашем приложении мы собираемся использовать Консоль диспетчера пакетов (PMC), поэтому давайте сделаем это, набрав:

PM> Add-Migration InitialMigration

После того, как мы нажмем клавишу Enter, наша миграция будет завершена.

Действия, которые происходят за кулисами


Файл ApplicationContextModelSnapshot.cs содержит модель базы данных и обновляется каждый раз при добавлении новой миграции. Два других файла: InitialMigration и InitialMigration.Designer - это файлы, содержащие и описывающие вновь созданную миграцию.

Итак, если вы выполнили все шаги из предыдущих статей, содержимое файла InitialMigration должно выглядеть следующим образом:

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

Применение созданной миграции

После того, как мы успешно создали нашу миграцию, мы должны применить ее, чтобы изменения вступили в силу в базе данных. Существует несколько способов применения миграции (с использованием сценариев SQL, с использованием метода Database.Migrate или с использованием методов командной строки), и, как мы делали с созданием, мы собираемся использовать подход методов командной строки.

Для консоли диспетчера пакетов команда:

Update-Database [options]

Для окна командной строки команда:

dotnet ef database update [options]

Поскольку мы уже определились с PMC, давайте откроем окно PMC и выполним команду:

После нажатия клавиши Enter мы увидим все различные действия, которые EF Core выполняет для нас, чтобы применить созданную миграцию. В результате у нас будет таблица Student , созданная со всей предоставленной конфигурацией из предыдущих статей:


Есть еще несколько важных фактов, которые нам нужно знать о миграции EF Core. Если мы проверим нашу базу данных, мы найдем еще одну созданную таблицу: _EFMigrationsHistory . EF Core использует эту таблицу для отслеживания всех примененных миграций. Таким образом, это означает, что если мы создадим еще одну миграцию в нашем коде и применим ее, EF Core применит только недавно созданную миграцию.

Но как EF Core узнает, какую миграцию нужно применить?

Ну, он сохраняет уникальный идентификатор в _EFMigrationsHistory , который представляет собой уникальное имя файла миграции, созданного при миграции, и никогда больше не выполняет файлы с тем же именем:


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

Добавление собственного кода в файл миграции

Мы уже объяснили назначение методов Up и Down в нашем файле InitialMigration . Но весь код в этих методах генерируется EF Core. При необходимости мы также можем добавить наш собственный код. Мы можем использовать параметр MigrationBuilder для доступа к широкому спектру методов, которые могут помочь нам в этом процессе. Одним из таких методов является метод Sql , который мы можем использовать для добавления желаемого пользовательского кода.

Итак, давайте откроем класс InitialMigration и изменим его, добавив наш собственный код:

Мы должны убедиться, что метод Sql в методе Down выполняет противоположные действия, если мы решим удалить нашу миграцию.

Теперь мы можем удалить нашу базу данных (просто для имитации начального состояния на сервере SQL) и снова применить нашу миграцию (нам не нужно ее создавать, она уже создана).

Создание миграции, если объекты и файлы Dbcontext находятся в отдельном проекте

Сейчас наша модель и классы контекста находятся в основном проекте вместе с файлами миграции. Но во многих реальных проектах модели и классы контекста находятся в отдельном проекте. Для таких проектов выполнение миграции было бы невозможно с настройкой, как в нашем проекте.

Попробуем продемонстрировать, что мы имеем в виду.

PM> Install-Package Microsoft.EntityFrameworkCore -Version 3.1.0

PM> Install-Package Microsoft.EntityFrameworkCore.Relational -Version 3.1.0

Затем нам нужно добавить ссылку на проект Entities в нашем основном проекте.


Как только мы это сделаем, нам нужно изменить пространство имен в классах ApplicationContext и Student с EFCoreApp.Entities на просто Сущности . Кроме того, мы должны сделать то же самое для директив using в классе Startup и в всех трех файлах миграции.

После всего этого наш проект должен успешно собраться.

Добавление новой миграции

Теперь мы можем попробовать добавить еще одну миграцию, набрав:

PM> Add-Migration TestMigrationFromSeparateProject

Все, что нам нужно сделать, это изменить нашу сборку миграции, поэтому давайте сделаем именно это в классе Startup :

Теперь мы можем снова запустить ту же команду, но на этот раз она будет выполнена успешно. Мы успешно создали нашу новую миграцию вместе с файлами миграции в папке Migrations :


Мы видим, что в файле TestMigration нет кода в методах Up и Down , и это нормально, потому что мы не изменить что-либо, но мы выполнили требуемую задачу.

Удаление миграции

Мы узнали, как создавать миграции из отдельного проекта. Но в результате мы создали пустую миграцию, которая ничего не делает в нашей базе данных. Когда мы создаем миграцию, которая нас не устраивает, мы можем легко удалить ее, набрав команду Remove-Migration [options] в окне PMC. Итак, давайте сделаем это:

Через несколько секунд наша предыдущая миграция будет удалена:


Отлично, теперь мы можем двигаться дальше.

Исходные данные в Entity Framework Core

В большинстве наших проектов мы хотим иметь некоторые исходные данные в созданной базе данных. Итак, как только мы выполним наши файлы миграции для создания и настройки базы данных, мы захотим заполнить ее некоторыми исходными данными. Это действие называется заполнением данных.

Мы можем создать код для действия заполнения в методе OnModelCreating с помощью ModelBuilder , как мы это сделали для конфигурации Fluent API. Итак, давайте добавим несколько строк в таблицу Student :

Итак, мы используем метод HasData , чтобы информировать EF Core о данных, которые он должен заполнить. Остальная часть кода не требует пояснений, потому что мы просто добавляем необходимые данные. Мы не используем свойство IsRegularStudent , потому что мы создали конфигурацию для этого свойства, чтобы иметь значение по умолчанию.

Теперь мы можем создать новую миграцию:

PM> Add-Migration SeedInitialData

И примените его:

Мы можем проверить нашу таблицу, чтобы проверить результат:


Лучший способ применения конфигурации и начального числа данных

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

EF Core предоставляет лучший способ создания конфигурации Fluent API с помощью интерфейса IEntityTypeConfiguration<T> . Используя его, мы можем разделить конфигурацию для каждой сущности на отдельный класс конфигурации.

Итак, давайте посмотрим, как это сделать.

В проекте Entities мы собираемся создать новую папку Configuration и внутри нового класса StudentConfiguration :

Конечно, мы не хотим генерировать исключение (это код по умолчанию после того, как VS реализует интерфейс), поэтому давайте изменим этот метод:

Этот код немного отличается от старого кода OnModelCreating , поскольку нам больше не нужно использовать часть .Entity<Student> . Это потому, что наш объект построителя уже имеет тип EntityTypeBuilder<Student> . Мы добавили дополнительный объект для вставки, просто чтобы было что создать миграцию.

Все, что нам нужно сделать, это изменить метод OnModelCreating :

Теперь мы можем добавить новую миграцию и применить ее:

PM> Add-Migration AdditionalRowInserted


Настройте начальную миграцию сразу после запуска приложений

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

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

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

Что ж, мы покажем вам, как именно это сделать.

Создание метода расширения

Давайте создадим новый класс MigrationManager в проекте Entities . Это будет статический класс, потому что мы собираемся создать метод расширения для запуска всех миграций при запуске приложения:

Теперь нам нужно установить библиотеку Microsoft.ASPNetCore.Hosting.Abstractions (она нужна нам для типа IHost, который мы собираемся использовать в нашем методе расширения) и добавить MigrateDatabase метод расширения для этого класса:

Мы используем тип IHost , потому что это позволяет нам связать этот метод в файле Program.cs и, конечно же, как вы можете видеть, он нам нужен для основной логики. .

Итак, мы создаем область службы и используем ее с ServiceProvider для получения экземпляра класса ApplicationContext . В первой статье мы обсудили свойства, содержащиеся в классе DbContext , и теперь мы используем один из них (базу данных) для вызова метода Migrate для выполнения миграции.

Применение метода MigrateDatabase

Следующим шагом является вызов этого метода в классе Program.cs :

Наконец, давайте удалим таблицы Student и _EFMigrationsHistory из базы данных и удалим хранимую процедуру в папке Programmability, чтобы имитировать пустую базу данных (или просто отбросим вашу базу данных: D). Затем мы можем запустить наше приложение. Мы увидим журналы в окне консоли, которые сообщают нам, что миграции выполняются. После того, как миграции завершили свою работу, мы можем проверить базу данных, чтобы убедиться, что все таблицы и процедуры были созданы снова.

Откат и создание сценариев миграции

В одном из предыдущих разделов мы узнали, как откатить миграцию, если мы ее не применили. Но в случае, если у нас есть, мы не можем удалить его просто так, нам нужно вернуть его к конкретной миграции.

Итак, чтобы показать, как работает возврат миграции, мы собираемся добавить еще одну строку в класс StudentConfiguration , создать, применить миграцию и затем вернуть ее к предыдущим значениям.

Сначала добавим в начальное число еще одну строку:

Тогда давайте создадим:

PM> Add-Migration RevertTestMigration

и примените миграцию:

В базе данных мы видим, что добавлена новая строка. Но так как мы не удовлетворены этим переносом (гипотетически), давайте вернем его:

PM> Update-Database AdditionalRowInserted

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

Наконец, если мы хотим создать сценарий SQL для всех наших миграций, мы можем сделать это, набрав:

Эта команда создаст для нас файл сценария.

Заключение

Итак, мы узнали много различной информации о миграции данных и о том, как ее использовать в различных ситуациях в EF Core.

Читайте также: