Dotnet

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

Проблема

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

Предположим: у вас есть демо-приложение некоей библиотеки, и для её представления необходимо, чтобы в базе данных уже содержались данные. Другой пример использования: каждая копия вашего приложения работает с собственной базой данных, и вам нужно во время установки или при первом запуске наполнить её исходным содержанием.

Создать базу данных — это не проблема, особенно если проект использует технологию доступа к данным Entity Framework (Core): всё можно сделать буквально в одной строке кода. Совсем другое дело — заполнение базы данных: ни в .NET, ни в Entity Framework готовых решений этой задачи нет.

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

Решение

Существует масса разных способов решить все эти задачи.

Попробуем сделать это с помощью утилиты DbTool и библиотеки Korzh.DbUtils. Это проекты с открытым кодом, которые можно найти на GitHub.

DbTool — это универсальный инструмент .NET Core: его можно установить на любой компьютер с .NET Core SDK одной простой командой. С помощью этой программы мы будем экспортировать информацию нашей базы данных в какой-нибудь формат, подходящий для распределения (JSON или XML).

Затем включим в проект файл (или файлы) с полученными данными и задействуем библиотеку Korzh.DbUtils для инициализации нашей базы данных при первом запуске приложения.

Этап 1: Экспортируем данные из БД с помощью DbTool

1.1 Установка DbTool

Благодаря своей универсальности, утилиту DbTool можно установить на компьютер и затем использовать как любую другую шелл-команду в системе. Для установки потребуется .NET Core SDK версии 2.1 (или выше).

Установить DbTool просто. Открываем терминал и вводим следующую команду:

dotnet tool install -g Korzh.DbTool

Если сразу же запустить команду dbtool, появится подробная справка со списком всех имеющихся команд.

1.2 Регистрация соединения БД

Сначала надо добавить соединение к нашей базе данных:

dbtool connections add {YourConnectionId} {DbType} {YourConnectionString}

Где:

  • {YourConnectionId} — это любой ID, который вы хотите присвоить этому соединению.
  • DbType— это тип сервера базы данных. На момент написания этой статьи DbTool (версия 1.1.4) поддерживала SQL Server (mssql) и базы данных MySQL (mysql).
  • Последний параметр в этой команде — это строка соединения. Та же, что уже используется вами в проекте для соединения БД.

Пример:

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

dbtool connections list

1.3 Экспорт данных

Добавив соединение, мы можем экспортировать базу данных с помощью команды export:

dbtool export {ConnectionId} [--format = xml | json] [--output = path] [--zip = filename]

Любые параметры, приведённые выше, можно опустить. Например, следующая команда:

dbtool export MyDb01 --zip = MyDbData.zip

создаст в текущем каталоге ZIP-архив с именем MyDbData.zip и заполнит его кучей файлов с данными в формате JSON (по умолчанию). Содержимое каждой таблицы БД хранится в отдельном файле с расширением .json.

Этап 2: Добавляем код пополнения данных в приложение

Теперь покажем, как использовать файл, созданный на предыдущем этапе, для инициализации БД в проекте ASP.NET Core. Процедуру, которая будет описана ниже, можно применять к любому проекту, созданному с .NET Core или .NET Framework версии 4.6.1 и выше.
Предполагается, что наш проект здесь использует технологию доступа к данным Entity Framework (Core), так что сама база данных создаётся автоматически средствами EF (с использованием метода EnsureCreated либо метода Migrate). Оговоримся также, что наша БД работает под сервером SQL (или его локальным вариантом). Приведённые здесь инструкции почти идентичны тем, что применяются для БД MySQL.

2.1 Добавление к проекту файла с данными

Прежде всего, к проекту надо добавить файл MyDbData.zip. Лучшее место для этого — папка App_Data, находящаяся внутри папки с вашим проектом. 

Обратите внимание, что вам также надо будет включить этот файл в свой проект вручную для проектов .NET Framework.

2.2. Установка пакетов Korzh.DbUtils

Для наших задач нам потребуются следующие 2 пакета NuGet:

  • Korzh.DbUtils.Import
  • Korzh.DbUtils.SqlServer (или Korzh.DbUtils.MySql в случае использования базы данных MySQL)

Для установки пакетов можно использовать диспетчер пакетов NuGet Package Manager либо консоль NuGet, а можно добавить их вручную (как тег <ProjectReference...>) прямо в файл .csproj.

2.3. Добавление кода инициализации

Теперь надо создать экземпляр класса DbInitializer и вызвать его метод Seed при первом запуске. Лучшее место для этой процедуры — метод Configure нашего класса Startup:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    .     .     .     .    app.UseMvc();
    //добавляем следующий фрагмент кода в конце вашего метода Configure, 
    используя (var scope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
    используя (var context = scope.ServiceProvider.GetService<AppDbContext>()) {
        //следующие строки запустятся, только если база данных не была создана ранее
        if (context.Database.EnsureCreated()) { 
            Korzh.DbUtils.DbInitializer.Create(options => {
                //устанавливаем строку соединения для нашей базы данных
                options.UseSqlServer(Configuration.GetConnectionString("MyDemoDb"));
                options.UseZipPacker(System.IO.Path.Combine(env.ContentRootPath, "App_Data", "MyDbData.zip"));
            })
            .Seed();
        }
    }
}

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

В этом случае потребуется добавить лишь один вызов в конце метода Startup.Configure:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    .  .  .  .
    app.UseMvc();    //Инициализация демо-версии базы данных (в случае необходимости)
    app.EnsureDbInitialized(Configuration, env);
}

Вот и всё.

Очень надеюсь, что представленное в статье решение сэкономит вам время. Спасибо за внимание.

Читайте также:

А еще вы можете проверить ваши знания:


Перевод статьи Sergiy Korzh: Easy data seeding in .NET (Core) applications