Упражнение. Настройка миграции
В этом уроке вы создадите классы сущностей C#, которые будут сопоставляться с таблицами в локальной базе данных SQLite. Функция миграции EF Core создает таблицы из этих сущностей.
Миграция позволяет постепенно обновлять схему базы данных.
Получение файлов проекта
Чтобы приступить к работе, получите файлы проекта. У вас есть несколько вариантов получения файлов проекта:
- Использование GitHub Codespaces
- Клонирование репозитория GitHub
Если у вас установлена совместимая среда выполнения контейнеров, вы также можете использовать расширение Dev Containers , чтобы открыть репозиторий в контейнере с предварительно установленными инструментами.
Использование GitHub Codespaces
Codespace — это интегрированная среда разработки, размещенная в облаке. Если вы используете GitHub Codespaces, перейдите в репозиторий в браузере. Выберите Код, а затем создайте новое codespace в main
ветви.
Клонирование репозитория GitHub
Если вы не используете GitHub Codespaces, вы можете клонировать репозиторий проекта GitHub, а затем открыть файлы как папку в Visual Studio Code.
Откройте командный терминал и клонируйте проект из GitHub с помощью командной строки:
git clone https://github.com/MicrosoftDocs/mslearn-persist-data-ef-core
Перейдите в папку mslearn-persist-data-ef-core и откройте проект в Visual Studio Code:
cd mslearn-persist-data-ef-core code .
Просмотр кода
Теперь у вас есть файлы проекта для работы. Ознакомьтесь с тем, что находится в проекте, и просмотрите код.
- Проект, ASP.NET Core веб-API, находится в каталоге ContosoPizza. Пути к файлам, на которые ссылаются в этом модуле, относятся к каталогу ContosoPizza .
- Services/PizzaService.cs — это класс службы, который определяет методы создания, чтения, обновления и удаления (CRUD). Все методы сейчас выдают исключение
System.NotImplementedException
. - В Program.cs
PizzaService
регистрируется в системе внедрения зависимостей ASP.NET Core. - Controllers/PizzaController.cs — это значение для
ApiController
, которое предоставляет конечную точку для команд HTTP POST, GET, PUT и DELETE. Эти команды вызывают соответствующие методы CRUD вPizzaService
.PizzaService
вставляется вPizzaController
конструктор . - Папка Models содержит модели, используемые
PizzaService
иPizzaController
. - Модели сущностей Pizza.cs, Topping.cs и Sauce.cs связаны следующим образом:
- Пицца может иметь одну или несколько начинок.
- Начинку можно использовать на одной или нескольких пиццах.
- Пицца может иметь один соус, но соус можно использовать на многих пиццах.
Сборка приложения
Чтобы создать приложение в Visual Studio Code:
На панели Обозреватель щелкните правой кнопкой мыши каталог ContosoPizza и выберите Открыть во встроенном терминале.
Откроется панель терминала с областью действия каталога ContosoPizza .
Создайте приложение с помощью следующей команды:
dotnet build
Компиляция кода должна пройти успешно без предупреждений или ошибок.
Добавление пакетов NuGet и инструментов EF Core
Ядро СУБД, с которым вы работаете в этом модуле, — SQLite. SQLite — это упрощенное файловое ядро СУБД. Это хороший выбор для разработки и тестирования, а также для небольших рабочих развертываний.
Примечание
Как упоминалось ранее, поставщики баз данных в EF Core являются подключаемыми. SQLite — хороший выбор для этого модуля, так как он является упрощенным и кроссплатформенным. Вы можете использовать один и тот же код для работы с разными ядрами СУБД, такими как SQL Server и PostgreSQL. В одном приложении можно даже использовать несколько ядр СУБД.
Перед началом работы добавьте необходимые пакеты:
В области терминала выполните следующую команду:
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
Эта команда добавляет пакет NuGet с поставщиком базы данных SQLite Entity Framework Core и всеми его зависимостями, в том числе с общими службами Entity Framework Core.
Выполните следующую команду:
dotnet add package Microsoft.EntityFrameworkCore.Design
Эта команда добавляет пакеты, необходимые для средств EF Core.
Для завершения выполните следующую команду:
dotnet tool install --global dotnet-ef
Эта команда устанавливает инструмент
dotnet ef
, который будет использоваться для создания миграций и формирования шаблонов.Совет
Если
dotnet ef
компонент уже установлен, его можно обновить, запустивdotnet tool update --global dotnet-ef
.
Модели формирования шаблонов и DbContext
Теперь вы добавляете и настраиваете реализацию DbContext
. DbContext
— это шлюз, через который можно взаимодействовать с базой данных.
Щелкните правой кнопкой мыши каталог ContosoPizza и добавьте новую папку с именем Data.
В папке Данные создайте файл с именем PizzaContext.cs. Добавьте следующий код в пустой файл:
using Microsoft.EntityFrameworkCore; using ContosoPizza.Models; namespace ContosoPizza.Data; public class PizzaContext : DbContext { public PizzaContext (DbContextOptions<PizzaContext> options) : base(options) { } public DbSet<Pizza> Pizzas => Set<Pizza>(); public DbSet<Topping> Toppings => Set<Topping>(); public DbSet<Sauce> Sauces => Set<Sauce>(); }
В приведенном выше коде:
- Конструктор принимает параметр с типом
DbContextOptions<PizzaContext>
. Конструктор позволяет внешнему коду передавать конфигурацию, чтобы один и тот жеDbContext
код можно было совместно использовать для тестового и рабочего кода и даже использовать с разными поставщиками. - Свойства
DbSet<T>
соответствуют таблицам, создаваемым в базе данных. - Имена таблиц будут соответствовать именам свойства
DbSet<T>
в классеPizzaContext
. При необходимости это поведение можно переопределить. - Если создать экземпляр класса
PizzaContext
, он предоставит свойстваPizzas
,Toppings
иSauces
. Изменения, внесенные в коллекции, предоставляемые этими свойствами, будут распространены в базу данных.
- Конструктор принимает параметр с типом
В Program.cs замените
// Add the PizzaContext
следующим кодом:builder.Services.AddSqlite<PizzaContext>("Data Source=ContosoPizza.db");
Предыдущий код:
- Регистрируется
PizzaContext
в системе внедрения зависимостей ASP.NET Core. - Указывает, что
PizzaContext
будет использовать поставщик базы данных SQLite. - Определяет строку подключения SQLite, которая указывает на локальный файл ContosoPizza.db.
Примечание
SQLite использует локальные файлы базы данных, поэтому, вероятно, можно жестко запрограммировать строку подключения. Для сетевых баз данных, таких как PostgreSQL и SQL Server, строки подключения всегда должны храниться безопасно. Для разработки в локальной среде используйте диспетчер секретов. Для рабочих развертываний рассмотрите возможность использования такой службы, как Azure Key Vault.
- Регистрируется
В файле Program.cs также замените
// Additional using declarations
приведенным ниже кодом.using ContosoPizza.Data;
Этот код разрешает зависимости на предыдущем шаге.
Сохраните изменения. GitHub Codespaces автоматически сохраняет изменения.
Выполните сборку приложения в терминале, выполнив команду
dotnet build
. Сборка должна завершиться успешно без предупреждений или ошибок.
Создание и выполнение миграции
Затем создайте миграцию, которую можно использовать для создания начальной базы данных.
Выполните следующую команду, чтобы создать миграцию для создания таблиц базы данных:
dotnet ef migrations add InitialCreate --context PizzaContext
В предыдущей команде используются следующие параметры.
- Миграции присваивается имя InitialCreate.
- Параметр
--context
задает имя класса в проекте ContosoPizza, который является производным отDbContext
.
Новый каталог Migrations отображается в корне проекта ContosoPizza. Каталог содержит файл с описанием <timestamp>_InitialCreate.cs изменений базы данных, которые необходимо перевести в скрипт изменений языка определения данных (DDL).
Выполните следующую команду, чтобы применить миграцию InitialCreate:
dotnet ef database update --context PizzaContext
Эта команда применяет миграцию. ContosoPizza.db не существует, поэтому миграция создается в каталоге проекта.
Совет
Средство
dotnet ef
поддерживается на всех платформах. В Visual Studio в Windows можно использоватьAdd-Migration
командлеты иUpdate-Database
PowerShell в окне интегрированной консоли диспетчера пакетов .
Проверка базы данных
В EF Core создана база данных для вашего приложения. Затем заглянут в базу данных с помощью расширения SQLite.
На панели Обозреватель щелкните правой кнопкой мыши файл ContosoPizza.db и выберите Открыть базу данных.
В области Обозреватель появится папка SQLite Обозреватель.
Выберите папку SQLite Обозреватель, чтобы развернуть узел и все его дочерние узлы. Щелкните правой кнопкой мыши ContosoPizza.db и выберите Показать таблицу "sqlite_master" , чтобы просмотреть полную схему базы данных и ограничения, созданные миграцией.
- Были созданы таблицы, соответствующие каждой сущности.
- Таблицы именованы согласно именам свойств
DbSet
вPizzaContext
. - Свойства с именами
Id
были выведены как автоматически добавочные поля первичного ключа. - Соглашения об именовании ограничений первичного и внешнего ключей EF Core :
PK_<primary key property>
иFK_<dependent entity>_<principal entity>_<foreign key property>
соответственно. Заполнители<dependent entity>
и<principal entity>
соответствуют именам классов сущностей.
Примечание
Как и ASP.NET Core MVC, EF Core использует подход к конфигурации. Соглашения EF Core сокращают время разработки путем определения намерения разработчика. Например, свойство с именем
Id
или<entity name>Id
понимается как первичный ключ созданной таблицы. Если вы решили не применять соглашение об именовании, к свойству требуется добавить заметочный атрибут[Key]
или его необходимо настроить в качестве ключа в методеOnModelCreating
вDbContext
.
Изменение модели и обновление схемы базы данных
Ваш руководитель Contoso Pizza предлагает вам новые требования, поэтому вам придется изменить модели сущностей. На следующих шагах вы измените модели с помощью атрибутов сопоставления (иногда называемых заметками к данным).
В файле Models\Pizza.cs внесите следующие изменения:
- Добавьте директиву
using
дляSystem.ComponentModel.DataAnnotations
. - Добавьте атрибут
[Required]
перед свойствомName
, чтобы пометить свойство как обязательное. - Добавьте атрибут
[MaxLength(100)]
перед свойствомName
, чтобы задать максимальную длину строк в 100 символов.
using System.ComponentModel.DataAnnotations; namespace ContosoPizza.Models; public class Pizza { public int Id { get; set; } [Required] [MaxLength(100)] public string? Name { get; set; } public Sauce? Sauce { get; set; } public ICollection<Topping>? Toppings { get; set; } }
- Добавьте директиву
В файле Models\Sauce.cs внесите следующие изменения:
- Добавьте директиву
using
дляSystem.ComponentModel.DataAnnotations
. - Добавьте атрибут
[Required]
перед свойствомName
, чтобы пометить свойство как обязательное. - Добавьте атрибут
[MaxLength(100)]
перед свойствомName
, чтобы задать максимальную длину строк в 100 символов. - Добавьте свойство типа
bool
с именемIsVegan
.
using System.ComponentModel.DataAnnotations; namespace ContosoPizza.Models; public class Sauce { public int Id { get; set; } [Required] [MaxLength(100)] public string? Name { get; set; } public bool IsVegan { get; set; } }
- Добавьте директиву
В файле Models\Topping.cs внесите следующие изменения:
- Добавьте директивы
using
дляSystem.ComponentModel.DataAnnotations
иSystem.Text.Json.Serialization
. - Добавьте атрибут
[Required]
перед свойствомName
, чтобы пометить свойство как обязательное. - Добавьте атрибут
[MaxLength(100)]
перед свойствомName
, чтобы задать максимальную длину строк в 100 символов. - Сразу после свойства
Name
добавьте свойство типаdecimal
с именемCalories
. - Добавьте свойство
Pizzas
типаICollection<Pizza>?
, чтобы создать связь "много ко многим"Pizza
-Topping
. - Добавьте атрибут
[JsonIgnore]
к свойствуPizzas
.
Важно!
Эти действия не позволяют
Topping
сущностямPizzas
включать свойство , когда код веб-API сериализует ответ в JSON. Без этого изменения сериализованная коллекция начинок будет включать в себя коллекцию каждой пиццы, которая использует начинку. Каждая пицца в этой коллекции будет содержать коллекцию начинок, которые, опять-таки, будут содержать коллекцию объектов пиццы. Бесконечный цикл такого типа называется циклической ссылкой, и его нельзя сериализовать.using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; namespace ContosoPizza.Models; public class Topping { public int Id { get; set; } [Required] [MaxLength(100)] public string? Name { get; set; } public decimal Calories { get; set; } [JsonIgnore] public ICollection<Pizza>? Pizzas { get; set; } }
- Добавьте директивы
Сохраните все изменения и запустите
dotnet build
.Выполните следующую команду, чтобы создать миграцию для создания таблиц базы данных:
dotnet ef migrations add ModelRevisions --context PizzaContext
Создается миграция с именем ModelRevisions.
Примечание
Появится следующее сообщение: Операция была сформирована шаблоном, что может привести к потере данных. Проверьте правильность миграции. Сообщение появляется, так как вы изменили связь с
Pizza
Topping
"один ко многим" на "многие ко многим", что требует удаления существующего столбца внешнего ключа. Так как у вас еще нет данных в базе данных, это изменение не проблематично. Однако в целом рекомендуется проверка созданной миграции, когда появится это предупреждение, чтобы убедиться, что никакие данные не удалены или не усечены в результате миграции.Выполните следующую команду, чтобы применить миграцию ModelRevisions:
dotnet ef database update --context PizzaContext
В строке заголовка папки SQLite Обозреватель нажмите кнопку Обновить базы данных.
В папке SQLite Обозреватель щелкните правой кнопкой мыши ContosoPizza.db. Выберите пункт Отобразить таблицу sqlite_master, чтобы просмотреть полную схему базы данных и ограничения.
Важно!
Расширение SQLite повторно использует открытые вкладки SQLite .
- Создана промежуточная таблица
PizzaTopping
для представления связи многие ко многим между объектами пиццы и начинки. - Добавлены новые поля в
Toppings
иSauces
.Calories
определен как столбец типаtext
, так как в SQLite нет соответствующего типаdecimal
.- Аналогичным образом
IsVegan
определен как столбец с типомinteger
. SQLite не определяет типbool
. - В обоих случаях преобразованием управляет EF Core.
- Столбец
Name
в каждой таблице помечен какnot null
, но в SQLite нет ограниченияMaxLength
.
Совет
Поставщики баз данных EF Core сопоставляют схему модели с функциями конкретной базы данных. Хотя SQLite не реализует соответствующее ограничение для
MaxLength
, другие базы данных, такие как SQL Server и PostgreSQL, делают это.- Создана промежуточная таблица
В папке SQLite Обозреватель щелкните таблицу правой
_EFMigrationsHistory
кнопкой мыши и выберите пункт Показать таблицу. Таблица содержит список всех миграций, которые применяются к базе данных. Так как вы выполнили две миграции, есть две записи: одна для миграции InitialCreate , а другая для ModelRevisions.
Примечание
В этом упражнении использовались атрибуты сопоставления (заметки к данным) для сопоставления моделей с базой данных. В качестве альтернативы атрибутам сопоставления можно использовать текучий API ModelBuilder для настройки моделей. Оба подхода допустимы, но некоторые разработчики предпочитают один подход другому.
Вы использовали миграции для определения и обновления схемы базы данных. В следующем уроке вы выполните методы в PizzaService
, которые управляют данными.