Предыдущий ролик Следующий ролик  

Видео урок: Running Entity Framework Code First Migrations

Основы ASP.NET MVC 5

В этом видео мы поговорим о том, как с помощью функции Code First Migrations фреймворка Entity Framework обновить схему базы данных, созданной в предыдущем видео, таким образом, чтобы она синхронизировалась с нашими классами моделей. Давайте подробнее рассмотрим таблицу CheckingAccounts, только что созданную в Обозревателе серверов. Entity Framework уже выполнил немалую работу, благодаря чему в этой таблице отображается соответствующая информация, но я хочу внести сюда еще несколько изменений. Во-первых, AccountNumber необязательно должен иметь тип nvarchar(MAX). Мне не нужно, чтобы в этом столбце поддерживались разные языки, поэтому будет достаточно типа varchar.

Мы уже говорили, что количество знаков в номере счета должно быть от 6 до 10, поэтому пусть это будет тип varchar(10). Я мог бы внести эти изменения прямо здесь или в SQL Server Management Studio, но нам хочется, чтобы созданное приложение можно было легко настраивать или разворачивать в других средах. Лучше всего вносить изменения в класс CheckingAccount. Что касается AccountNumber, как видите, регулярное выражение никак не влияет на тип создаваемого столбца.

Было бы неправильно использовать это свойство. Можно раскомментировать валидатор StringLength и удалить это минимальное значение. Но еще мне хотелось бы вместо NVARCHAR использовать VARCHAR, поэтому я явно укажу это с помощью атрибута Column. Воспользуемся клавишей Ctrl+., для того чтобы разрешить эту ссылку. Пусть TypeName будет равен "varchar". Только не вводите здесь varchar(10), потому что инструмент этого не поймет и это приведет к неявной ошибке.

Нажмем теперь клавишу Ctrl+F5 для запуска приложения. Поскольку я уже вошел в систему, мы получаем весьма информативное сообщение об ошибке, в котором говорится, что после того как Entity Framework создал эту базу данных, в нее были внесены какие-то изменения, и к сожалению, приложение не может обновить данную базу, но для решения проблемы предлагает использовать функцию Code First Migrations. Итак, перейдем в меню "Сервис" (Tools) и выберем пункт Диспетчер пакетов библиотек -> Консоль диспетчера пакетов. Entity Framework - один из множества пакетов NuGet, используемых нами в MVC-приложении. Управление миграциями - одна из тех возможностей, которые предоставляет нам консоль диспетчера пакетов.

Первой введем команду Enable-Migrations. Эта команда принимает параметр -ContextType, к которому мы добавим название нашего DbContext - ApplicationDbContext. Как видите, консоль обнаружила существующую базу данных, а также создала первоначальную миграцию в новой папке под названием "Migrations". Можно рассматривать это как исходную точку, которая будет использоваться в рамках определения тех изменений, которые нужно будет вносить впоследствии, если мы продолжим изменять модели.

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

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

Кроме того, мы можем напрямую отредактировать созданный файл миграции. Метод Up используется для применения изменений. Как видите, параметр maxLength имеет значение 10, unicode - значение "false", поскольку мы перешли от NVARCHAR к VARCHAR. Метод Down используется для отката изменений. При необходимости можно создать SQL-скрипт. Например, если нам нужно вручную применить эти обновления к другому серверу. Для этого мы используем команду Update-Database с флагом -Script.

Большая часть этих данных - всего лишь значения для таблицы MigrationHistory, но в самом верху можно увидеть операторы для изменения столбца AccountNumber. Если мы хотим прямо сейчас применить эти изменения к базе данных, воспользуемся командой Update-Database без флага -Script, но при этом можно добавить флаг -Verbose, чтобы действительно увидеть, что же делает эта команда. Назначение этого флага мы рассмотрим позднее во время выполнения метода Seed. Кроме того, можно вернуться к предыдущему состоянию, воспользовавшись переключателем -TargetMigration и указав название конкретной миграции.

А пока позвольте мне показать вам, что если прокрутить вверх эти данные MigrationHistory, то можно увидеть, что на самом деле изменения уже были внесены. Попробуем теперь зарегистрироваться, но сначала вспомните, что в методе Register мы жестко закодировали параметр AccountNumber. Теперь, когда я знаю, что этот метод работает, можно быстро все поправить. Укажем, к примеру, что значение AccountNumber должно определяться следующим образом: 123456 + количество текущих счетов, имеющихся на данный момент в базе данных. IntelliSense слегка запутался, поскольку мы пропустили знак равенства.

Количество текущих счетов, на данный момент имеющихся в базе данных, можно определить с помощью db.CheckingAccounts.Count. Преобразуем результат в строку и добавим слева столько нулей, чтобы количество знаков в номере счета стало равно 10. Впоследствии будем использовать полученное значение вместо жестко закодированного. Очевидно, тут есть несколько проблем. 123456 - это произвольное число, которое либо не стоит использовать вообще, либо стоит как минимум хранить в конфигурационном файле.

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

Откроем файл Configuration.cs из папки Migrations и установим для AutomaticMigrationsEnabled значение "true". Теперь немножко изменим файл CheckingAccount.cs. Возможно, вы заметили, что ApplicationUserID из CheckingAccount был создан в виде нулевого столбца. Если для этого свойства нельзя использовать нулевые значения, необходимо добавить свойство Required или лучше добавить атрибут Required к этому свойству. При включенной автоматической миграции все, что мне нужно сделать для отправки этих изменений в базу данных, - выполнить команду Update-Database и снова применить флаг -Verbose.

Но теперь Entity Framework немного беспокоится по поводу возможной потери данных. Для решения этой проблемы нам предлагается два варианта, и мы выбираем опцию -Force, что говорит о том, что сейчас нас это не волнует. Это видео помогает понять, какие возможности вам предоставляются при использовании функции Code First Migrations фреймворка Entity Framework для синхронизации кода со схемой базы данных. Не забывайте, что весь код, анализируемый нами в этой главе, можно найти в файлах упражнений, размещенных в папке Chapter 3 -> Final.

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