Entity Framework Core подключение к MS SQL

Все исходники /  Язык программирования C# /  OS Windows /  Web ASP.NET /  MS SQL и сайты на ASP.NET / Entity Framework Core подключение к MS SQL

ASP.NET и MS SQL

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

Сайты построенные на ASP.NET, как, впрочем, и динамические сайты на других платформах и языках, могут использовать различные системы баз данных. Например: MS SQL, MySql, Sqlite, PostgreSQL, Firebird и другие.

В статье речь пойдет о системе баз данных MS SQL Server. Построим взаимодействие с базой данных через драйвер объектно-реляционного сопоставления Entity Framework Core. Практический пример оформлен в виде сайта на платформе ASP.NET MVC и прикреплён в конце статьи.

Модуль Entity Framework Core

Entity Framework Core – технология объектно-ориентированного доступа к данным. При работе с базами данных через модуль EF Core запрошенная таблица преобразуется в экземпляр класса, а столбцы в одноименные свойства. Изменения значений свойств сохраняется в базе данных.

При работе с Entity Framework Core классы модели базы данных сопоставляются таблицам базы. Инкапсуляция реляционных запросов превращает работу с базами данных в «обычное» объектно-ориентированное программирование. В отличие от этого драйверы реляционного доступа, возвращают данные в виде таблицы или параметров, которые требуют дополнительной обработки.

Создание веб приложения ASP.NET MVC

Последовательность создания веб приложения в MS Visual Studio:

  • Создание проекта
  • Фильтрация: язык C#, Все платформы, Веб проект
  • Веб приложение ASP.NET Core
  • ASP.NET Core Web App (Model-View-Controller). Опции: Настроить для HTTPS, Enable Razor runtime Compilation
  • Создание веб приложения

Более подробное описание создания веб приложения ASP.NET Core MVC.

Установка необходимых пакетов NuGet

Для использования возможностей объектно-реляционного сопоставления «объект - база данных» необходима установка приложение пакета Microsoft.EntityFrameworkCore.

Кроме этого, понадобится установка расширений SqlServerDbContextOptionsExtensions. UseSqlServer для этого необходимо в веб приложение добавить пакет Microsoft.EntityFrameworkCore. SqlServer. Это необходимо для настройки контекста и создания строк подключения с помощью построителей.

База данных для исследования

Создадим базу данных MS SQL. Для этого необходим MS SQL Server или MS SQL Server Express и MS SQL Server Management Studio. Создавать таблицы и связи между ними будем посредством инструмента управления MS SQL Server Management Studio. Базу данных назовем DBMSSQL. Добавим в базу три небольшие таблицы кратко описывающие науки и ее разделы.

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

  • PK (primary key) – первичный ключ
  • FK (foreign key) – ключ внешней связи
  • UI (unique index) – уникальный индекс

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

Модуль Entity Framework Core осуществляет доступ к базам данных посредством моделей. Модель – классы, определенные в соответствии таблицам базы данных. Entity Framework Core сопоставляет столбец таблицы и одноименное свойство класса соответствующей таблицы данных.

Соответственно таблицам создадим классы модели для базы данных DBMSSQL. Все таблицы в базе имеют одинаковые столбцы Id, Name, NumberViews, Uri. Чтобы уменьшить количество повторного программного кода создадим абстрактный класс с общими свойствами. Далее этот класс унаследуют классы модели базы данных.

Листинг модели базы данных:
namespace ASPSQLEF.Models
{
    // Класс содержащий общие столбцы для всех таблиц.
    public abstract class UniTable
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int NumberViews { get; set; }
        public string Uri { get; set; }
    }

    public class Science : UniTable
    {
        // Список дочерних записей связанных с конкретным элементом таблицы Sciences. 
        public List<Section> Sections { get; set; }
    }

    public class Section : UniTable
    {
        // Список связанных дочерних данных. 
        public List<SubSection> SubSections { get; set; }

        // Внешний ключ указывающий на родительский объект.
        public int ScienceId { get; set; }
        // Связанный родительский объект
        public Science Science { get; set; }
    }

    public class SubSection : UniTable
    {
        // У самой нижней таблицы в иерархии отношений нет дочерних объектов.
        // Есть только свойства указывающие на родительский объект.
        public int SectionId { get; set; }
        public Section Section { get; set; }
    }
}

Контекст сеанса с базой данных DBContext

Контекст баз данных представляется классом DBContext, необходимым для взаимодействия с базами данных. Объект класса производного от DBContext позволяет выполнять запросы и сохранять изменения, произведенные над свойствами экземпляров модели.

Во время взаимодействия с базой данных класс контекста наполняет классы модели информацией из таблиц базы данных. Сеанс взаимодействия контекста с базой данных краток, и состоит из одного цикла:

  • Создание объекта класса контекста
  • Получение данных (сохранение изменений)
  • Закрытие сеанса и удаление экземпляра контекста

Для наполнения классов модели информацией из базы в классе контекста необходимо определить свойства DbSet<TEntity>, где роль сущности (Entity) будут исполнять классы модели.

Класс DbSet<TEntity> - это оболочка для сущности (типа объекта таблицы базы данных), которой являются классы модели. Включение экземпляра класса DbSet<TEntity> в контекст означает, что он включен в модель Entity Framework Core. Свойства DbSet<TEntity> автоматически инициализируются при создании экземпляра класса контекста. Имена свойств, представляющих классы модели, должны быть идентичны названиям соответствующих таблиц в базе данных.

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

Листинг класса контекста для взаимодействия с базой данных DBMSSQL:
public class SqlDBContext : DbContext
{
    // Названия объектов обязательно должны совпадать с названиями соответствующих таблиц.
    public DbSet<SubSection> SubSections /*имя таблицы*/ { get; set; }
    public DbSet<Section> Sections /*имя таблицы*/ { get; set; }
    public DbSet<Science> Sciences /*имя таблицы*/ { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // Контекст получает строку подключения.
        optionsBuilder.UseSqlServer(Constants.SqlConnectionSQLServer);
    }
} 

Строка подключения к SQL серверу

Реквизиты подключения к определенной базе данных, для контекста, указываются в строке подключения (connection string). Строку подключения к MS SQL Server удобно создавать с помощью построителей. Например, с помощью класса SqlConnectionStringBuilder, входящего в состав пространства имён Microsoft.Data.SqlClient (пакет Microsoft.EntityFrameworkCore.SqlServer). Таким способом создаётся синтактически правильная строка подключения к серверу базы данных.

Строка подключения отправляет серверу информацию для идентификации клиента, способе проверки клиента и выборе базы данных для последующих запросов. Разные режимы проверки подлинности пользователя требуют соответствующее содержание строки подключения.

Режим проверки подлинности Windows использует имя и пароль пользователя, зарегистрированного в операционной системе. При режиме проверки подлинности SQL Server требуются имя и пароль учетной записи пользователя зарегистрированной на SQL сервере.

Листинг двух вариантов строк подключения к SQL серверу:
public class Constants
{
    // Проверка подлинности Windows
    public static string SqlConnectionIntegratedSecurity
    {
        get
        {
            var sb = new SqlConnectionStringBuilder
            {
                DataSource = "Путь к серверу SQL",
                // Подключение будет с проверкой подлинности пользователя Windows
                IntegratedSecurity = true,
                // Название целевой базы данных.
                InitialCatalog = "DBMSSQL"
            };

            return sb.ConnectionString;
        }
    }


    // Проверка подлинности SQL сервером
    public static string SqlConnectionSQLServer
    {
        get
        {
            var sb = new SqlConnectionStringBuilder
            {
                DataSource = "Путь к серверу SQL",
                IntegratedSecurity = false,
                InitialCatalog = "DBMSSQL",
                UserID = "Имя пользователя",
                Password = "Пароль"
            };

            return sb.ConnectionString;
        }
    }
}

Выполнение запросов к базе данных

Подключение к базе данных в веб приложении происходит при создании экземпляра класса контекста SqlDBContext. Экземпляр контекст создаётся в конструкторе контроллера HomeController.

public class HomeController : Controller
{
    private readonly SqlDBContext _dBContext;

    public HomeController()
    {
        // Происходит подключение к серверу SQL и базе данных указанных
        // в строке подключения.
        _dBContext = new SqlDBContext();
    }
    ...
}

После создания объекта контекста можно выполнять запросы к базе данных. В представления полученная информация передаётся в виде слабо-типизированных ViewBag и строго-типизированных объектов посредством Model.

public class HomeController : Controller
{
    ...
    public IActionResult EntityFrameworkCore()
    {
        // Динамические свойства будут хранить списки объектов с данными
        // полученных из соответствующих таблиц базы.
        ViewBag.SubSections = _dBContext.SubSections.ToList();
        ViewBag.Sections = _dBContext.Sections.ToList();
        ViewBag.Sciences = _dBContext.Sciences.ToList();

        return View();
    }


    // Постепенно упрощаются конструкции и мощная asp.net 
    // становится всё проще и проще для понимания.
    // Устанавливается URL маршрут для метода Action.
    [Route("science-{uri}")]
    public IActionResult Science(string uri)
    {
        Science science = _dBContext.Sciences.
            // Выбор записи таблицы по уникальному Uri.
            Where(sc => sc.Uri == uri).
            // Получение дочерних связанных данных.
            Include(sc => sc.Sections).
                // Вывод будет включать данные субдочерних объектов принадлежащих дочернему.
                ThenInclude(sec => sec.SubSections).FirstOrDefault();

        // Инкрементирование счётчика просмотра данных таблицы Sciences.
        science.NumberViews++;
        // Сохранение изменённых данных.
        _dBContext.SaveChanges();

        // Отправка в представление сформированной модели.
        return View(science);
    }
    ...
}

Представление с моделью

В представлении данные из модели извлекаются оператором перебора коллекции foreach. Код C# внедряется посредством разметки (движка веб страниц) Razor.

Листинг представления с моделью:
...
<section>
    <h4 class="mb-0 text-danger">@Model.Name</h4>
    <p class="text-muted">Количество просмотров - @Model.NumberViews</p>
    <ul>
        <li>
            Разделы:
            <ul>
                @foreach (Section s in Model.Sections)
                {
                    <li>
                        <a href="/section-@s.Uri">@s.Name</a>
                        <ul>
                            @foreach (SubSection subsection in s.SubSections)
                            {
                                <li><a href="/subsection-@subsection.Uri">@subsection.Name</a></li>
                            }
                        </ul>
                    </li>
                }
            </ul>
        </li>
    </ul>
</section>

Представление с ViewBag

Полученные данные можно передавать в представления динамическими переменными. Слаботипизированная переменная ViewBag может передавать любой объект, и что удобно, не требует приведения типов при присваивании соответствующему объекту.

В нашем случае в представление передаются списки объектов с информацией, полученной из базы данных. Путём перебора элементов списков, используя минимум кода Razor и разметки HTML, информация выводится в браузер в удобочитаемом виде.

Листинг представления с применением динамического свойства ViewBag:
...
@{
    // При присваивании объекту соответствующего класса не требуется приведения типов.
    List<SubSection> SubSections = ViewBag.SubSections;
    List<Section> Sections = ViewBag.Sections;
    List<Science> Sciences = ViewBag.Sciences;
}


<div class="row mt-5">
    <div class="col-lg-4 col-md-6">
        <header class="text-center mb-3">
            <h5 class="mb-0 text-danger">Таблица Sciences</h5>
            <p>Список наук</p>
        </header>
        <dl>
            @foreach (Science item in Sciences)
            {
                <dt class="text-danger">@item.Name</dt>
                <dd class="ml-4 mb-0">Id: @item.Id</dd>
                <dd class="ml-4 mb-0">NumberViews: @item.NumberViews</dd>
                <dd class="ml-4 mb-4">URL: <a href="/science-@item.Uri">Таблица науки</a></dd>
            }
        </dl>
    </div>
    <div class="col-lg-4 col-md-6">
        <header class="text-center mb-3">
            <h5 class="mb-0 text-danger">Таблица Sections</h5>
            <p>Разделы наук</p>
        </header>
        <dl>
            @foreach (Section item in Sections)
            {
                <dt class="text-danger">@item.Name</dt>
                <dd class="ml-4 mb-0">Id: @item.Id</dd>
                <dd class="ml-4 mb-0">NumberViews: @item.NumberViews</dd>
                <dd class="ml-4 mb-4">URL: <a href="/section-@item.Uri">Таблица раздела</a></dd>
            }
        </dl>
    </div>
    <div class="col-lg-4 col-md-6">
        <header class="text-center mb-3">
            <h5 class="mb-0 text-danger">Таблица SubSections</h5>
            <p>Подразделы разделов наук</p>
        </header>
        <dl>
            @foreach (SubSection item in SubSections)
            {
                <dt class="text-danger">@item.Name</dt>
                <dd class="ml-4 mb-0">Id: @item.Id</dd>
                <dd class="ml-4 mb-0">NumberViews: @item.NumberViews</dd>
                <dd class="ml-4 mb-4">URL: 
                    <a href="/subsection-@item.Uri">Таблица подраздела</a>
                </dd>
            }
        </dl>
    </div>
</div>

Необходимое для работы с исходником

  • Сервер баз данных - MS SQL Server, MS SQL Server Express или в крайнем случае можно использовать локальный сервер MSSQLLocalDB, идущий в составе Visual Studio).
  • MS SQL Server Management Studio для создания и редактирования таблиц.
  • Среда программирования MS Visual Studio 2019

Прикрепленный исходник

Файл содержит файл базы данных и исходный код веб приложения ASP.NET Core .NET 5. Перед работой с прикреплённым веб приложением рекомендуется изучить данную статью.

Скачать исходник

  • Файл: aspsqlef.zip
  • Размер: 1467 Кбайт
  • Загрузки: 52