Первое приложение EF Core

Первое приложение, использующее EF Core будет консольным. В нем мы немного познакомимся с ORM-технологией, лежащей в основе EF Core. Также, это приложение поможет нам, в дальнейшем, увидеть некоторые особенности, использования EF Core с другими технологиями, например, с Blazor Server.

Предварительная настройка

Как и было сказано во введении, все примеры в руководстве по EF Core будут использовать MySQL. Поэтому, для работы нам потребуется зарегистрироваться на сайте mysql.com, скачать и установить необходимые инструменты для работы c MySQL. Для работы с базами данных я буду использовать MySQL Workbench. Для начала создадим новое подключение к базе данных MySQL. Для этого, находясь на главной странице MySQL Workbench необходимо нажать кнопку «Setup new connection»:

setup new connection

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

  • Connection name: efcore
  • Connection Method: Standard (TCP/IP)
  • Host Name: 127.0.0.1
  • Port: 3306
  • UserName: admin
  • Password: test
  • Default Schema: не задано (при необходимости, можем определить это свойство позднее)

Теперь необходимо кликнуть левой кнопкой мыши по созданному соединению

Подключившись к MySQL нам необходимо создать новую схему (базу данных MySQL)

 

Назовем нашу первую БД users и все остальные настройки новой схемы оставим по умолчанию:

После того, как нажмем Apply, MySQL Workbench ещё раз в отдельном окне попросит подтвердить создание новой схемы — подтверждаем. После этого, в списке Schemas появится новая пока ещё пустая база данных:

 

На этом предварительная подготовка к созданию первого приложения с EF Core закончена. Теперь перейдем в Visual Studio и напишем наше приложение.

Создание консольного приложения с EF Core и MySQL

Итак, создадим новое консольное приложение в Visual Studio:

Новое консольное приложение Visual Studio

Чтобы начать работать с EF Core и MySQL нам необходимо установить все необходимые пакеты. Для этого воспользуемся менеджером пакетов NuGet. Первый пакет — Microsoft.EntityFrameworkCore:

Microsoft.EntityFrameworkCore

Этот пакет добавит в наш проект основной функционал EF Core. Чтобы мы могли работать в EF Core с MySQL, необходимо установить пакет, содержащий провайдер для этой базы данных. В перечне всех поставщиков баз данных на сайте Microsoft нам рекомендуется использовать провайдер, содержащийся в пакете Pomelo.EntityFrameworkCore.MySql. Устанавливаем этот пакет:

Pomelo.EntityFrameworkCore.MySql

Теперь все пакеты установлены и можно приступать к разработке логики нашего приложения.

Модель данных

EF Core использует модель метаданных для описания и сопоставления типов сущностей приложения с базой данных. По сути, моделью данных может выступать как один класс C#, так и группа классов, которые могут быть как связаны между собой, так и быть независимыми друг от друга. Так как мы вначале создали БД с именем users, то, соответственно, первым классом, описывающим модель данных, у нас будет класс User:

namespace EFCoreApp.Models
{
    public class User
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public string? Email { get; set; }
        public int Age { get; set; }
    }
}
Обычно, все модели я храню в отдельной папке «Models» проекта, поэтому, по умолчанию все модели данных у меня содержатся в пространстве имен %ProjectName%.Models

Как видите, наша модель — это обычный класс C#. Однако, так как объекты этого класса будут выступать сущностями EF Core, у класса определено свойство Id, которое будет выступать в качестве уникального ключа. Каждое свойство нашего класса будет в дальнейшем сопоставлено с отдельным столбцом таблицы БД. По умолчанию, при генерации таблиц БД EF Core в качестве первичных ключей рассматривает свойства с именами Id или с именами вида [Имя_класса]Id. То есть, в нашем случае, мы могли бы определить свойство UserId и в EF Core это свойство использовалось бы по умолчанию как первичный ключ.

Создание контекста данных

Для взаимодействия с базой данных в EF Core используются специальный классы — контексты данных, которые наследуются от класса DbContext. Поэтому, создадим такой класс и назовем его ApplicationContext:

using Microsoft.EntityFrameworkCore;
using EFCoreApp.Models;
using Pomelo.EntityFrameworkCore.MySql;

namespace EFCoreApp
{
    public class ApplicationContext: DbContext
    {

        private const string _connection = @"server=127.0.0.1;Port=3306;user=admin;password=test;database=users";

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

        public ApplicationContext()
        {
            _ = Database.EnsureCreated();
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseMySql(_connection, ServerVersion.AutoDetect(_connection));
        }
    }
}

Рассмотрим по порядку, что содержит наш класс и как он работает. Во-первых, внутри класса мы определили константу, содержащую строку подключения к MySQL:

private const string _connection = @"server=127.0.0.1;Port=3306;user=admin;password=test;database=users";

Параметры подключения, которые мы использовали — представлены в разделе выше.

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

Далее, мы определили свойство:

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

DbSet — это, как и DbContext, специальный класс, используемый в EF Core для хранения набора сущностей определенного класса. В нашем случае, модель состоит всего из одного класса, поэтому и свойство мы определили одно.

Далее, мы переопределили метод OnConfiguring класса DbContext. В этом методе мы настраиваем подключение к базе данных:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseMySql(_connection, ServerVersion.AutoDetect(_connection));
}

В этом методе мы используем параметр optionsBuilder класса DbContextOptionsBuilder для настройки подключения к MySQL. Метод UseMySQL имеет несколько переопределенных версий и, в нашем случае, принимает два параметра: первый — строка подключения и второй — версия сервера MySQL. Так как версия сервера MySQL может измениться или же мы вовсе можем не знать с какой версией сервера мы будем в дальнейшем работать, то для получения значения этого параметра мы использовали статический метод класса ServerVersion.AutoDetect, который и определит за нас версию сервера.

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

public ApplicationContext()
{
    _ = Database.EnsureCreated();
}

Создав контекст данных, можно переходить далее. Наполним нашу базу данных начальными данными

Присвоение начальных данных

Самый простой способ наполнить нашу базу начальными данными — это добавить эти данные до начала основной логики приложения. Например, это можно сделать следующим образом (в файле Program.cs нашего консольного приложения):

using EFCoreApp.Models;

namespace EFCoreApp
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using var db = new ApplicationContext();
            if (db.Users.Any() == false) //нет никаких данных в БД
            {
                //создаем нового пользователя
                User user = new()
                {
                    Name = "admin",
                    Age = 30,
                    Email = "admin@corp.gov"
                };
                //добавляем запись в БД
                db.Users.Add(user);
                db.SaveChanges();
            }    

            //получаем всех пользователей из БД
            List<User> users = db.Users.ToList();
            foreach (User user in users) 
            {
                Console.WriteLine($"{user.Id} {user.Name} {user.Email} {user.Age}");
            }
        }
    }
}

Опять же, рассмотрим по порядку, что мы здесь написали. Первое:

using var db = new ApplicationContext();

Класс ApplicationContext через своего предка (базовый класс DbContext) реализует интерфейс IDisposable, поэтому для работы с ApplicationContext мы можем использовать конструкцию using. После того, как надобность в использовании класса отпадет, ресурсы, используемые классом, будут автоматически освобождены.

Далее мы, используя метод LINQ проверяем есть ли какая-либо информация в БД:

if (db.Users.Any() == false)

Если коллекция Users будет пуста, то метод Any вернет False. Соответственно, если коллекция пуста, то далее мы создаем объект класса User:

User user = new()
{
    Name = "admin",
    Age = 30,
    Email = "admin@corp.gov"
};

И далее, добавляем новый объект в коллекцию и сохраняем изменения:

db.Users.Add(user);
db.SaveChanges();

После этого, мы получаем список пользователей из БД и выводим его в консоль:

List<User> users = db.Users.ToList();
foreach (User user in users) 
{
    Console.WriteLine($"{user.Id} {user.Name} {user.Email} {user.Age}");
}

При первом запуске приложения мы увидим следующую информацию в консоли:

1 admin admin@corp.gov 30

Стоит обратить внимание на то, что при создании объекта мы не присваивали значение свойству Id, однако, при записи объекта в БД это свойство было присвоено объекту автоматически.

Теперь мы можем снова вернуться в MySQL Workbench и посмотреть на содержимое нашей БД. Вот так выглядит теперь база данных:

Имя таблицы соответствует имени коллекции сущностей в контексте — в ApplicationContext коллекция имеет названия Users, а в БД создана таблица users. Имена полей таблицы соответствуют именам свойств класса. В DDL наша таблица будет выглядеть следующим образом (всё это сделано EF Core):

CREATE TABLE `users` (
  `Id` int NOT NULL AUTO_INCREMENT,
  `Name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
  `Email` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
  `Age` int NOT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

Итого

Таким образом, Entity Framework Core обеспечивает простое управление сущностями из базы данных, избавляя нас от непосредственной работы с конкретной базой данных — создание БД, таблиц в ней и прочие рутинные операции выполняются EF Core на основании классов модели и контекста данных.

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