From 45b507bf79ea79cb047aff88e03a6f9a252bdea0 Mon Sep 17 00:00:00 2001 From: Toastie <toastie@toastiet0ast.com> Date: Sat, 25 Jan 2025 19:53:36 +1300 Subject: [PATCH] fixed migration scripts, moved migration code to dbservice --- src/EllieBot/Db/EllieDbService.cs | 68 +++++++++++++++++++++++++++---- src/EllieBot/MigrationRunner.cs | 54 ------------------------ src/EllieBot/migrate.ps1 | 12 ++---- src/EllieBot/migrate.sh | 13 +++--- 4 files changed, 69 insertions(+), 78 deletions(-) delete mode 100644 src/EllieBot/MigrationRunner.cs diff --git a/src/EllieBot/Db/EllieDbService.cs b/src/EllieBot/Db/EllieDbService.cs index eb45520..f035a1d 100644 --- a/src/EllieBot/Db/EllieDbService.cs +++ b/src/EllieBot/Db/EllieDbService.cs @@ -1,18 +1,22 @@ using LinqToDB.Common; using LinqToDB.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; using EllieBot.Migrations; namespace EllieBot.Db; -public sealed class EllieDbService : DbService +public sealed class EllieDbService : DbService { private readonly IBotCredsProvider _creds; // these are props because creds can change at runtime - private string DbType => _creds.GetCreds().Db.Type.ToLowerInvariant().Trim(); - private string ConnString => _creds.GetCreds().Db.ConnectionString; - + private string DbType + => _creds.GetCreds().Db.Type.ToLowerInvariant().Trim(); + + private string ConnString + => _creds.GetCreds().Db.ConnectionString; + public EllieDbService(IBotCredsProvider creds) { LinqToDBForEFTools.Initialize(); @@ -28,14 +32,14 @@ public sealed class EllieDbService : DbService await using var context = CreateRawDbContext(dbType, connString); - await MigrationRunner.RunMigration(context); - + await RunMigration(context); + // make sure sqlite db is in wal journal mode if (context is SqliteContext) { await context.Database.ExecuteSqlRawAsync("PRAGMA journal_mode=WAL"); } - + // await context.Database.MigrateAsync(); } @@ -53,7 +57,7 @@ public sealed class EllieDbService : DbService throw new NotSupportedException($"The database provide type of '{dbType}' is not supported."); } } - + private EllieContext GetDbContextInternal() { var dbType = DbType; @@ -74,4 +78,52 @@ public sealed class EllieDbService : DbService public override EllieContext GetDbContext() => GetDbContextInternal(); + + private static async Task RunMigration(DbContext ctx) + { + // if database doesn't exist, run the baseline migration + if (!await ctx.Database.CanConnectAsync()) + { + Log.Information("Database does not exist. Creating a new database..."); + await ctx.Database.MigrateAsync(); + return; + } + + // get the latest applied migration + + var applied = await ctx.Database.GetAppliedMigrationsAsync(); + + // get all .sql file names from the migrations folder + var available = Directory.GetFiles("Migrations/Sqlite", "*_*.sql") + .Select(x => Path.GetFileNameWithoutExtension(x)) + .OrderBy(x => x); + + var lastApplied = applied.Last(); + Log.Information("Last applied migration: {LastApplied}", lastApplied); + + // apply all mirations with names greater than the last applied + foreach (var runnable in available) + { + if (string.Compare(lastApplied, runnable, StringComparison.Ordinal) < 0) + { + Log.Warning("Migration {MigrationName} has not been applied yet", runnable); + + var query = await File.ReadAllTextAsync(GetMigrationPath(ctx.Database, runnable)); + await ctx.Database.ExecuteSqlRawAsync(query); + } + } + + // run all migrations that have not been applied yet + } + + private static string GetMigrationPath(DatabaseFacade ctxDatabase, string runnable) + { + if (ctxDatabase.IsSqlite()) + return $"Migrations/Sqlite/{runnable}.sql"; + + if (ctxDatabase.IsNpgsql()) + return $"Migrations/PostgreSql/{runnable}.sql"; + + throw new NotSupportedException("This database type is not supported."); + } } \ No newline at end of file diff --git a/src/EllieBot/MigrationRunner.cs b/src/EllieBot/MigrationRunner.cs deleted file mode 100644 index bc5a895..0000000 --- a/src/EllieBot/MigrationRunner.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; - -namespace EllieBot.Migrations; - -public class MigrationRunner -{ - public static async Task RunMigration(DbContext ctx) - { - // if database doesn't exist, run the baseline migration - if (!await ctx.Database.CanConnectAsync()) - { - Log.Information("Database does not exist. Creating a new database..."); - await ctx.Database.MigrateAsync(); - } - - // get the latest applied migration - - var applied = await ctx.Database.GetAppliedMigrationsAsync(); - - // get all .sql file names from the migrations folder - var available = Directory.GetFiles("Migrations/Sqlite", "*_*.sql") - .Select(x => Path.GetFileNameWithoutExtension(x)) - .OrderBy(x => x); - - string lastApplied = applied.Last(); - Log.Information("Last applied migration: {LastApplied}", lastApplied); - - // apply all mirations with names greater than the last applied - foreach (var runnable in available) - { - if (string.Compare(lastApplied, runnable, StringComparison.Ordinal) < 0) - { - Log.Warning("Migration {MigrationName} has not been applied yet", runnable); - - var query = await File.ReadAllTextAsync(GetMigrationPath(ctx.Database, runnable)); - await ctx.Database.ExecuteSqlRawAsync(query); - } - } - - // run all migrations that have not been applied yet - } - - private static string GetMigrationPath(DatabaseFacade ctxDatabase, string runnable) - { - if (ctxDatabase.IsSqlite()) - return $"Migrations/Sqlite/{runnable}.sql"; - - if (ctxDatabase.IsNpgsql()) - return $"Migrations/PostgreSql/{runnable}.sql"; - - throw new NotSupportedException("This database type is not supported."); - } -} \ No newline at end of file diff --git a/src/EllieBot/migrate.ps1 b/src/EllieBot/migrate.ps1 index 5659147..af48e8a 100644 --- a/src/EllieBot/migrate.ps1 +++ b/src/EllieBot/migrate.ps1 @@ -8,10 +8,6 @@ Write-Output "Creating new migration..." # Step 1: Create initial migrations dotnet build -# Get previous migration IDs -$firstMigrationIdSqlite = (dotnet ef migrations list --context SqliteContext --no-build --no-connect | Select-Object -Last 2 | Select-Object -First 1) -split ' ' | Select-Object -First 1 -$firstMigrationIdPostgresql = (dotnet ef migrations list --context PostgresqlContext --no-build --no-connect | Select-Object -Last 2 | Select-Object -First 1) -split ' ' | Select-Object -First 1 - dotnet ef migrations add $MigrationName --context SqliteContext --output-dir "Migrations/Sqlite" --no-build dotnet ef migrations add $MigrationName --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build @@ -28,8 +24,8 @@ Write-Output "Generating diff SQL scripts..." $newMigrationIdSqlite = (dotnet ef migrations list --context SqliteContext --no-build --no-connect | Select-Object -Last 2 | Select-Object -First 1) -split ' ' | Select-Object -First 1 $newMigrationIdPostgresql = (dotnet ef migrations list --context PostgresqlContext --no-build --no-connect | Select-Object -Last 2 | Select-Object -First 1) -split ' ' | Select-Object -First 1 -dotnet ef migrations script ($firstMigrationIdSqlite -replace '^.*_', '') $MigrationName --context SqliteContext -o "Migrations/Sqlite/$newMigrationIdSqlite.sql" --no-build -dotnet ef migrations script ($firstMigrationIdPostgresql -replace '^.*_', '') $MigrationName --context PostgresqlContext -o "Migrations/Postgresql/$newMigrationIdPostgresql.sql" --no-build +dotnet ef migrations script init $MigrationName --context SqliteContext -o "Migrations/Sqlite/$newMigrationIdSqlite.sql" --no-build +dotnet ef migrations script init $MigrationName --context PostgresqlContext -o "Migrations/Postgresql/$newMigrationIdPostgresql.sql" --no-build if ($LASTEXITCODE -ne 0) { Write-Error "Error: Failed to generate SQL script" @@ -53,5 +49,5 @@ dotnet build # Step 4: Create new initial migrations Write-Output "Creating new initial migration..." -dotnet ef migrations add $MigrationName --context SqliteContext --output-dir "Migrations/Sqlite" --no-build -dotnet ef migrations add $MigrationName --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build \ No newline at end of file +dotnet ef migrations add init --context SqliteContext --output-dir "Migrations/Sqlite" --no-build +dotnet ef migrations add init --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build \ No newline at end of file diff --git a/src/EllieBot/migrate.sh b/src/EllieBot/migrate.sh index 5576f0e..1bce413 100644 --- a/src/EllieBot/migrate.sh +++ b/src/EllieBot/migrate.sh @@ -15,9 +15,6 @@ echo "Creating new migration..." dotnet build # Getting previous migration names in order to generate SQL scripts -FIRST_MIGRATION_ID_SQLITE=$(dotnet ef migrations list --context SqliteContext --no-build --no-connect | tail -2 | head -1 | cut -d' ' -f1) -FIRST_MIGRATION_ID_POSTGRESQL=$(dotnet ef migrations list --context PostgresqlContext --no-build --no-connect | tail -2 | head -1 | cut -d' ' -f1) - dotnet ef migrations add "${MIGRATION_NAME}" --context SqliteContext --output-dir "Migrations/Sqlite" --no-build dotnet ef migrations add "${MIGRATION_NAME}" --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build @@ -35,8 +32,8 @@ echo "Generating diff SQL scripts..." NEW_MIGRATION_ID_SQLITE=$(dotnet ef migrations list --context SqliteContext --no-build --no-connect | tail -2 | head -1 | cut -d' ' -f1) NEW_MIGRATION_ID_POSTGRESQL=$(dotnet ef migrations list --context PostgresqlContext --no-build --no-connect | tail -2 | head -1 | cut -d' ' -f1) -dotnet ef migrations script "${FIRST_MIGRATION_ID_SQLITE#*_}" $MIGRATION_NAME --context SqliteContext -o "Migrations/Sqlite/${NEW_MIGRATION_ID_SQLITE}.sql" --no-build -dotnet ef migrations script "${FIRST_MIGRATION_ID_POSTGRESQL#*_}" $MIGRATION_NAME --context PostgresqlContext -o "Migrations/Postgresql/${NEW_MIGRATION_ID_POSTGRESQL}.sql" --no-build +dotnet ef migrations script init $MIGRATION_NAME --context SqliteContext -o "Migrations/Sqlite/${NEW_MIGRATION_ID_SQLITE}.sql" --no-build +dotnet ef migrations script init $MIGRATION_NAME --context PostgresqlContext -o "Migrations/Postgresql/${NEW_MIGRATION_ID_POSTGRESQL}.sql" --no-build if [ $? -ne 0 ]; then @@ -78,8 +75,8 @@ for file in "Migrations/Postgresql"/*; do done # Step 4: Adding new initial migration +echo "Creating new initial migration..." dotnet build -echo "Creating new initial migration..." -dotnet ef migrations add "${MIGRATION_NAME}" --context SqliteContext --output-dir "Migrations/Sqlite" --no-build -dotnet ef migrations add "${MIGRATION_NAME}" --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build \ No newline at end of file +dotnet ef migrations add init --context SqliteContext --output-dir "Migrations/Sqlite" --no-build +dotnet ef migrations add init --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build \ No newline at end of file