Вступление
В этом руководстве я продемонстрирую на своём примере, как вы можете безболезненно разместить ваш проект. Надеюсь, кому-то пригодится. Обязательно просмотрите блок с дополнительной информацией.
Технологии
.NET 6 WebAPI
Heroku
Entity Framework Core 6
-
PostgreSQL
Heroku
Регистрируемся на сервисе Heroku. Трудностей быть не должно.
После подключения к GitHub выбираем наш репозиторий с WebAPI, предварительно выгруженный туда. Также окном ниже выбираем ветвь с приложением, которое загрузится на сервис.
А теперь важный аспект. Перед тем, как деплоить проект, его необходимо собрать.
Переходим во вкладку Settings и в пункте Buildpacks добавляем ссылку на "сборочный пакет" .NET 6.
Осталось следующее: установить аддон Heroku Postgres с помощью Configure Add-ons во вкладке Overview:
Кликаем по аддону и переходим во вкладку Settings >> View Credentials, где находятся данные о нашей БД. Они нам понадобятся.
Конфигурационные файлы
Переходим во вкладку Settings >> Config Vars и добавим конфигурационный файл под именем "ASPNETCORE_ENVIRONMENT"
. Это файл ключ-значение в котором будет удобно конфигурировать нашу рабочую среду между Development / Production
значениями.
Также здесь можно заметить такой файл как "DATABASE_URL"
. Это строка подключения к БД, предоставленная аддоном Heroku. Мы её будем использовать
Наш проект практически готов к публикации. Осталось его настроить.
Настройка проекта
Сразу скажу, что структура проекта, безусловно, может у каждого отличаться, но алгоритм действий будет одинаков при любом раскладе. Я продемонстрирую CRUD-проект. Условимся на том, что у вас объявлены соответствующие классы и сущности и осталось только настроить слой базы данных. Кратко ознакомимся.
Тема проекта: книжный магазин.
Приложение разделено на слои:
Domain (сущности)
Application (бизнес-логика)
Persistence (слой доступа к данным)
Presentation (web api)
Убедимся, что в сборке со слоем БД установлены все необходимые NuGet пакеты:
Если вы все делаете в одной сборке WebApi, этих пакетов будет достаточно.
Настройка контекста базы данных
Создадим интерфейс, который будет реализован контекстом BookStoreDbContext:
public interface IBookStoreDbContext
{
DbSet<Book> Books { get; set; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
Объявим необходимые таблицы и вызываем базовый конструктор. В этом же классе можно переопределить protected метод OnModelCreating(),
чтобы добавить начальные данные в таблицу, но это уже за рамками статьи.
public class BookStoreDbContext : DbContext, IBookStoreDbContext
{
public DbSet<Book> Books { get; set; }
public BookStoreDbContext(DbContextOptions<BookStoreDbContext> options)
: base(options) { }
}
Создадим класс DbInitializer
, который будет использоваться при старте приложения и методом Migrate()
создавать БД на основе нашего контекста, если её нет, а также программным способом накатывать миграции.
public class DbInitializer
{
public static void Initialize(BookStoreDbContext context)
{
context.Database.Migrate();
}
}
Переходим в файл конфигурации приложения appsettings.json
, где укажем строку подключения DbConnection
нашей локальной БД.
Вместо # - укажите ваши данные:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"DbConnection": "Host=localhost;Database=#;Username=#;"
},
"AllowedHosts": "*"
}
Внедрение зависимостей
Добавим класс DependencyInjection
для нашего контекста. В нем мы внедрим наш контекст базы данных.
Создадим метод GetConnectionString(),
который получит данные о строке подключения из конфигурационного файла Heroku "DATABASE_URL"
.
Если в конфигурационном файле указана среда "Development"
(разработка), то мы используем нашу локальную строку подключения к БД в файле asppsettings.json
с её строкой подключения.
Подключим PostgreSql
.
public static class DependencyInjection
{
public static IServiceCollection AddPersistence(
this IServiceCollection services,
IConfiguration configuration)
{
var connectionString = string.Empty;
/* Проверим, в какой мы среде*/
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
{
connectionString = configuration["DbConnection"];
}
else
{
connectionString = GetConnectionString();
}
services.AddDbContext<BookStoreDbContext>(options =>
{
/* Подключаем PostgreSQL */
options.UseNpgsql(connectionString);
});
services.AddScoped<IBookStoreDbContext>(provider =>
provider.GetService<BookStoreDbContext>());
return services;
}
public static string GetConnectionString()
{
/* Используем строку подключения из конфигурацинного файла, обеспеченного Heroku*/
var connectionUrl = Environment.GetEnvironmentVariable("DATABASE_URL");
connectionUrl = connectionUrl.Replace("postgres://", string.Empty);
var userPassSide = connectionUrl.Split("@")[0];
var hostSide = connectionUrl.Split("@")[1];
var user = userPassSide.Split(":")[0];
var password = userPassSide.Split(":")[1];
var host = hostSide.Split("/")[0];
var database = hostSide.Split("/")[1].Split("?")[0];
return $"Host={host};Database={database};Username={user};Password={password};SSL Mode=Require;Trust Server Certificate=true";
}
В файле Program.cs
нашего WebAPI внедрим контекст БД и вызовем необходимый метод Initialize()
:
using (var scope = app.Services.CreateScope())
{
try
{
var context = scope.ServiceProvider.GetRequiredService<BookStoreDbContext>();
DbInitializer.Initialize(context);
}
catch (Exception)
{
}
}
Добавим миграцию в проект с помощью команды add-migration Init:
Деплоим проект!
Вернёмся в Heroku и нажмём заветную кнопку Deploy Branch:
Заключение
Поздравляю! Можно переходить на сайт. Вы можете наблюдать за состоянием сборки вашего приложения во вкладке Activity.
В моём случае это получение информации о книгах.
Я надеюсь, что изложил максимально просто и понятно. Если исключить БД, то всего лишь необходимо подключить .NET buildpack и деплоить проект. Проблем быть не должно.
Всех благ!
Дополнительная информация
Heroku:
Ролик, который вдохновил меня на написание статьи:
https://www.youtube.com/watch?v=BqI1hu0gIb0&ab_channel=CoderFoundry
Аналогичная статья с размещением API вместе с Docker:
https://www.c-sharpcorner.com/article/deploy-a-net-api-to-heroku-through-github-actions/
Создание контекста БД и подключение PostgreSQL с помощью Entity Framework Core:
На всякий случай добавлю .NET Buildpack для размещения вашего приложения:
Более подробное описание добавления Entity Framework Core в проект:
Комментарии (5)
thedecadence
25.10.2022 09:25+4Хочу сделать поправку по самому началу "Регистрируемся на сервисе Heroku. Трудностей быть не должно".
Начиная с марта этого года для регистрация на Хероку для представителей РФ стала невозможной. Кроме того, для авторизации в личном кабинете и доступу к большинству бесплатных сервисов (и платных тоже, естественно) нужна привязка банковской карты, но карты российских банков и виртуальные карты хероку не принимает.
Также с 20 ноября хероку отменяет все бесплатные сервисы.
И ещё - у многих российских провайдеров имеются проблемы с доступом в личный кабинет хероку - приходится пользоваться vpn.
Поэтому я перевёл многие проекты на российские сервисы - благо их много, и они очень дешёвые по сравнению с зарубежными аналогами.
Сама статья интересная, многое применимо и к другим сервисам, похожими на Хероку, но её актуальность в данный момент имеется скорее для зарубежных разработчиков.
Godi Автор
25.10.2022 13:24Спасибо за комментарий.
Я использую российский провайдер, и с регистрацией проблем действительно не возникало. Не могли бы ли вы предоставить источник, в котором указано, что Heroku стал недоступным для пользователей РФ?
Что касается привязки банковской карты для использования сервисов - не уверен.
А с переходом на платную основу и вправду печально :с
thedecadence
25.10.2022 18:22+1Источник - сам Хероку. С апреля зарегистрироваться как пользователю РФ не даёт - вылезает соответствующее сообщение.
Mayhem924
25.10.2022 14:34+2Добавлю немного насчет метода Initialize
Вызывать миграцию программно таким образом неправильно:
context.Database.EnsureCreated(); context.Database.Migrate();
Пояснение из документации Microsoft
Не вызывайте EnsureCreated() перед Migrate(). EnsureCreated() обходит миграции, чтобы создать схему, что приводит к сбою Migrate().
thedecadence
Хочу сделать поправку по самому началу "Регистрируемся на сервисе Heroku. Трудностей быть не должно".
Начиная с марта этого года для регистрация на Хероку для представителей РФ стала невозможной. Кроме того, для авторизации в личном кабинете и доступу к большинству бесплатных сервисов (и платных тоже, естественно) нужна привязка банковской карты, но карты российских банков и виртуальные карты хероку не принимает.
Также с 20 ноября хероку отменяет все бесплатные сервисы.
И ещё - у многих российских провайдеров имеются проблемы с доступом в личный кабинет хероку - приходится пользоваться vpn.
Поэтому я перевёл многие проекты на российские сервисы - благо их много, и они очень дешёвые по сравнению с зарубежными аналогами.
Сама статья интересная, многое применимо и к другим сервисам, похожими на Хероку, но её актуальность в данный момент имеется скорее для зарубежных разработчиков.