VEU.WathBody/3-app/2-cli/Server.WatchBody.Web/Services/MigrationRunner.cs

49 lines
2.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Npgsql;
using Server.WatchBody.Core.Dal.Src.Repository;
using Server.WatchBody.Web.Db;
namespace Server.WatchBody.Web.Services;
/// <summary>
/// Режим --mode migrate (З-36, requirements 2.3): применение файлов
/// 2-db\migrations\ по возрастанию имён; файл не в журнале src.migration
/// — выполняется целиком в транзакции (скрипт + запись журнала), сбой —
/// откат и код возврата 1. Миграции идемпотентны (IF NOT EXISTS /
/// OR REPLACE) — повторный запуск безопасен.
/// </summary>
public class MigrationRunner(PostgresConnectionString connectionString)
{
public int Apply(string migrationsDir)
{
if (!Directory.Exists(migrationsDir))
throw new DirectoryNotFoundException($"каталог миграций не найден: {migrationsDir}");
var repository = new MigrationRepository(connectionString);
var applied = 0;
foreach (var file in Directory.GetFiles(migrationsDir, "*.sql")
.OrderBy(f => Path.GetFileName(f), StringComparer.Ordinal))
{
var name = Path.GetFileName(file);
if (repository.Select(name) != null) continue;
var sql = File.ReadAllText(file);
using (var scope = new System.Transactions.TransactionScope(
System.Transactions.TransactionScopeAsyncFlowOption.Enabled))
{
// скрипт и журнал — одна ambient-транзакция (оба соединения
// Npgsql, Enlist по умолчанию); сбой → откат всего файла
using (var connection = new NpgsqlConnection(connectionString.Value))
{
connection.Open();
using var command = new NpgsqlCommand(sql, connection);
command.ExecuteNonQuery();
}
repository.Insert(name);
scope.Complete();
}
Console.WriteLine($"миграция применена: {name}");
applied++;
}
return applied;
}
}