EF Core. Подключение к существующей базе данных MySQL

До этого момента, при работе EF Core мы использовали так называемый подход «Code First» — то есть, вначале мы определяли модель и контекст данных, а затем создавали базу данных и работали с ней. Такой подход вполне логичен и широко используется в работе. Однако, может возникнуть ситуация, при которой нам необходимо подключиться к уже готовой базе. И в этом случае могут возникнуть серьезные трудности при подходе «Code First»

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

Самая главная проблема подключения к уже существующей базе данных — это затраты времени.

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

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

Для таких ситуаций в EF Core может применяться подход «Database First», то есть, когда база данный первична и на её основе автоматически генерируются необходимые классы моделей и контекст данных. То есть, осуществляется Reverse Engineering.

Подключение к существующей базе MySQL

В предыдущей части мы уже разработали наше первое приложение Blazor Server для работы с MySQL. Давайте теперь воспользуемся созданной БД и напишем ещё одно приложение, в котором используем подход «Database First». Итак, создадим новое приложение Blazor Server:

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

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Tools
  • Pomelo.EntityFrameworkCore.MySql

Этих трех пакетов нам будет достаточно, чтобы провести reverse engineering нашей базы данных MySQL. Теперь, для реверса базы данных (создания необходимых классов C#) мы можем воспользоваться либо консолью PowerShell для разработчиков, либо консолью менеджера пакетов. Рассмотрим оба эти варианта.

Использования консоли менеджера пакетов

В Visual Studio в меню выбираем: Средства — Диспетчер пакетов NuGet — Консоль диспетчера пакетов

Теперь в этой консоли мы должны набрать команду следующего вида:

Scaffold-DbContext «строка_подключения» провайдер_БД

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

Scaffold-DbContext "server=127.0.0.1;Port=3306;user=admin;password=test;database=users;" Pomelo.EntityFrameworkCore.MySql

строка подключения взята из первого приложения с EF Core. После ввода команды мы увидим следующие сообщения в консоли:

Желтым выделено предупреждение о том, что стоит защитить потенциально конфиденциальную информацию о подключении. В самом проекте (в корне) мы увидим два класса C# — модель и контекст данных:

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

В меню Visual Studio выбираем: Средства — Командная строка — PowerShell для разработчиков:

Первая команда установить глобальный инструмент dotnet ef:

dotnet tool install --global dotnet-ef После успешного выполнения команды вы увидите следующее сообщение в консоли:

Теперь используем это средство для реверса базы данных:

dotnet ef dbcontext scaffold "server=127.0.0.1;Port=3306;user=admin;password=test;database=users;" Pomelo.EntityFrameworkCore.MySql

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

Содержимое созданных классов C#

Посмотрим на содержимое созданных файлов. Модель данных получилась следующая:

public partial class User
{
    public int Id { get; set; }

    public string? Name { get; set; }

    public string? Email { get; set; }

    public int Age { get; set; }
}

Класс модели определен как частичный. Но, в целом, полностью соответствует тому, который мы создавали вручную. С контекстом данных всё немного иначе:

public partial class UsersContext : DbContext
{
    public UsersContext()
    {
    }

    public UsersContext(DbContextOptions<UsersContext> options)
        : base(options)
    {
    }

    public virtual DbSet<User> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
        => optionsBuilder.UseMySql("server=127.0.0.1;port=3306;user=admin;password=test;database=users", Microsoft.EntityFrameworkCore.ServerVersion.Parse("8.0.26-mysql"));

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder
            .UseCollation("utf8mb4_0900_ai_ci")
            .HasCharSet("utf8mb4");

        modelBuilder.Entity<User>(entity =>
        {
            entity.HasKey(e => e.Id).HasName("PRIMARY");

            entity.ToTable("users");
        });

        OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

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

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.UseMySql("server=127.0.0.1;port=3306;user=admin;password=test;database=users", 
        Microsoft.EntityFrameworkCore.ServerVersion.Parse("8.0.26-mysql"));

В моем случае, это версия 8.0.26-mysql. EF Core правильно определила версию и, соответственно, эту же версию и использует для настройки подключения, но, лично мое мнение, лучше заменить конкретную версию на использование метода AutoDetect, как мы это делали ранее. Ну и, конечно же, строку подключение убрать из исходного кода и поместить её на период разработки, хотя бы в файл конфигурации.

Далее, в методе OnModelCreating производится настройка кодировок и ключей в моделях. В принципе, эту часть можно оставлять как есть.

Теперь, когда мы получили необходимые классы C# для работы с MySQL, мы можем зарегистрировать в нашем приложении Blazor Server фабрику контекстов, как мы это сделали в предыдущей части

builder.Services.AddDbContextFactory<UsersContext>();

и работать с базой.

using (var db = _db.CreateDbContext())
{
    List<User> users = db.Users.ToList();
}

При этом, так как в классе контекста данных у нас был переопределен метод OnConfiguring, то при создании фабрики не требуется передавать в параметрах настройки подключения.

Итого

Скачать код проекта из Github

В зависимости от ситуации, в EF Core могут использоваться два подхода в работе: 1) «Code First» в котором первичен код C# — описание модели, контекста и создание на основе этих данных таблиц БД. 2) «Database First» — в этом случае на первом месте стоит готовая база данных по которой мы генерируем необходимые классы C#, используя пакет Microsoft.EntityFrameworkCore.Tools в котором содержатся необходимые инструменты для реверс инжиниринга БД.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии