Упражнение. Настройка миграции

Завершено

В этом уроке вы создадите классы сущностей C#, которые будут сопоставляться с таблицами в локальной базе данных SQLite. Функция миграции EF Core создает таблицы из этих сущностей.

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

Получение файлов проекта

Чтобы приступить к работе, получите файлы проекта. У вас есть несколько вариантов получения файлов проекта:

  • Использование GitHub Codespaces
  • Клонирование репозитория GitHub

Если у вас установлена совместимая среда выполнения контейнеров, вы также можете использовать расширение Dev Containers , чтобы открыть репозиторий в контейнере с предварительно установленными инструментами.

Использование GitHub Codespaces

Codespace — это интегрированная среда разработки, размещенная в облаке. Если вы используете GitHub Codespaces, перейдите в репозиторий в браузере. Выберите Код, а затем создайте новое codespace в main ветви.

Клонирование репозитория GitHub

Если вы не используете GitHub Codespaces, вы можете клонировать репозиторий проекта GitHub, а затем открыть файлы как папку в Visual Studio Code.

  1. Откройте командный терминал и клонируйте проект из GitHub с помощью командной строки:

    git clone https://github.com/MicrosoftDocs/mslearn-persist-data-ef-core
    
  2. Перейдите в папку 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.csPizzaService регистрируется в системе внедрения зависимостей 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:

  1. На панели Обозреватель щелкните правой кнопкой мыши каталог ContosoPizza и выберите Открыть во встроенном терминале.

    Откроется панель терминала с областью действия каталога ContosoPizza .

  2. Создайте приложение с помощью следующей команды:

    dotnet build
    

    Компиляция кода должна пройти успешно без предупреждений или ошибок.

Добавление пакетов NuGet и инструментов EF Core

Ядро СУБД, с которым вы работаете в этом модуле, — SQLite. SQLite — это упрощенное файловое ядро СУБД. Это хороший выбор для разработки и тестирования, а также для небольших рабочих развертываний.

Примечание

Как упоминалось ранее, поставщики баз данных в EF Core являются подключаемыми. SQLite — хороший выбор для этого модуля, так как он является упрощенным и кроссплатформенным. Вы можете использовать один и тот же код для работы с разными ядрами СУБД, такими как SQL Server и PostgreSQL. В одном приложении можно даже использовать несколько ядр СУБД.

Перед началом работы добавьте необходимые пакеты:

  1. В области терминала выполните следующую команду:

    dotnet add package Microsoft.EntityFrameworkCore.Sqlite
    

    Эта команда добавляет пакет NuGet с поставщиком базы данных SQLite Entity Framework Core и всеми его зависимостями, в том числе с общими службами Entity Framework Core.

  2. Выполните следующую команду:

    dotnet add package Microsoft.EntityFrameworkCore.Design
    

    Эта команда добавляет пакеты, необходимые для средств EF Core.

  3. Для завершения выполните следующую команду:

    dotnet tool install --global dotnet-ef
    

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

    Совет

    Если dotnet ef компонент уже установлен, его можно обновить, запустив dotnet tool update --global dotnet-ef.

Модели формирования шаблонов и DbContext

Теперь вы добавляете и настраиваете реализацию DbContext . DbContext — это шлюз, через который можно взаимодействовать с базой данных.

  1. Щелкните правой кнопкой мыши каталог ContosoPizza и добавьте новую папку с именем Data.

  2. В папке Данные создайте файл с именем 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. Изменения, внесенные в коллекции, предоставляемые этими свойствами, будут распространены в базу данных.
  3. В 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.

  4. В файле Program.cs также замените // Additional using declarations приведенным ниже кодом.

    using ContosoPizza.Data;
    

    Этот код разрешает зависимости на предыдущем шаге.

  5. Сохраните изменения. GitHub Codespaces автоматически сохраняет изменения.

  6. Выполните сборку приложения в терминале, выполнив команду dotnet build. Сборка должна завершиться успешно без предупреждений или ошибок.

Создание и выполнение миграции

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

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

    dotnet ef migrations add InitialCreate --context PizzaContext
    

    В предыдущей команде используются следующие параметры.

    • Миграции присваивается имя InitialCreate.
    • Параметр --context задает имя класса в проекте ContosoPizza, который является производным от DbContext.

    Новый каталог Migrations отображается в корне проекта ContosoPizza. Каталог содержит файл с описанием <timestamp>_InitialCreate.cs изменений базы данных, которые необходимо перевести в скрипт изменений языка определения данных (DDL).

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

    dotnet ef database update --context PizzaContext
    

    Эта команда применяет миграцию. ContosoPizza.db не существует, поэтому миграция создается в каталоге проекта.

    Совет

    Средство dotnet ef поддерживается на всех платформах. В Visual Studio в Windows можно использовать Add-Migration командлеты и Update-Database PowerShell в окне интегрированной консоли диспетчера пакетов .

Проверка базы данных

В EF Core создана база данных для вашего приложения. Затем заглянут в базу данных с помощью расширения SQLite.

  1. На панели Обозреватель щелкните правой кнопкой мыши файл ContosoPizza.db и выберите Открыть базу данных.

    Снимок экрана: пункт меню

    В области Обозреватель появится папка SQLite Обозреватель.

    Снимок экрана: папка Обозреватель SQLite на панели Обозреватель.

  2. Выберите папку SQLite Обозреватель, чтобы развернуть узел и все его дочерние узлы. Щелкните правой кнопкой мыши ContosoPizza.db и выберите Показать таблицу "sqlite_master" , чтобы просмотреть полную схему базы данных и ограничения, созданные миграцией.

    Снимок экрана: развернутая папка sqLite Обозреватель на панели Обозреватель.

    • Были созданы таблицы, соответствующие каждой сущности.
    • Таблицы именованы согласно именам свойств 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 предлагает вам новые требования, поэтому вам придется изменить модели сущностей. На следующих шагах вы измените модели с помощью атрибутов сопоставления (иногда называемых заметками к данным).

  1. В файле Models\Pizza.cs внесите следующие изменения:

    1. Добавьте директиву using для System.ComponentModel.DataAnnotations.
    2. Добавьте атрибут [Required] перед свойством Name, чтобы пометить свойство как обязательное.
    3. Добавьте атрибут [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; }
    }
    
  2. В файле Models\Sauce.cs внесите следующие изменения:

    1. Добавьте директиву using для System.ComponentModel.DataAnnotations.
    2. Добавьте атрибут [Required] перед свойством Name, чтобы пометить свойство как обязательное.
    3. Добавьте атрибут [MaxLength(100)] перед свойством Name, чтобы задать максимальную длину строк в 100 символов.
    4. Добавьте свойство типа 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; }
    }
    
  3. В файле Models\Topping.cs внесите следующие изменения:

    1. Добавьте директивы using для System.ComponentModel.DataAnnotations и System.Text.Json.Serialization.
    2. Добавьте атрибут [Required] перед свойством Name, чтобы пометить свойство как обязательное.
    3. Добавьте атрибут [MaxLength(100)] перед свойством Name, чтобы задать максимальную длину строк в 100 символов.
    4. Сразу после свойства Name добавьте свойство типа decimal с именем Calories.
    5. Добавьте свойство Pizzas типа ICollection<Pizza>?, чтобы создать связь "много ко многим" Pizza-Topping.
    6. Добавьте атрибут [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; }
    }
    
  4. Сохраните все изменения и запустите dotnet build.

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

    dotnet ef migrations add ModelRevisions --context PizzaContext
    

    Создается миграция с именем ModelRevisions.

    Примечание

    Появится следующее сообщение: Операция была сформирована шаблоном, что может привести к потере данных. Проверьте правильность миграции. Сообщение появляется, так как вы изменили связь с PizzaTopping "один ко многим" на "многие ко многим", что требует удаления существующего столбца внешнего ключа. Так как у вас еще нет данных в базе данных, это изменение не проблематично. Однако в целом рекомендуется проверка созданной миграции, когда появится это предупреждение, чтобы убедиться, что никакие данные не удалены или не усечены в результате миграции.

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

    dotnet ef database update --context PizzaContext
    
  7. В строке заголовка папки SQLite Обозреватель нажмите кнопку Обновить базы данных.

    Снимок экрана: кнопка

  8. В папке 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, делают это.

  9. В папке SQLite Обозреватель щелкните таблицу правой _EFMigrationsHistory кнопкой мыши и выберите пункт Показать таблицу. Таблица содержит список всех миграций, которые применяются к базе данных. Так как вы выполнили две миграции, есть две записи: одна для миграции InitialCreate , а другая для ModelRevisions.

Примечание

В этом упражнении использовались атрибуты сопоставления (заметки к данным) для сопоставления моделей с базой данных. В качестве альтернативы атрибутам сопоставления можно использовать текучий API ModelBuilder для настройки моделей. Оба подхода допустимы, но некоторые разработчики предпочитают один подход другому.

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

Проверьте свои знания

1.

Какое соглашение об именовании существует в классе сущностей для первичного ключа?