fixed migration scripts, moved migration code to dbservice
This commit is contained in:
parent
211f610d28
commit
45b507bf79
4 changed files with 69 additions and 78 deletions
src/EllieBot
|
@ -1,18 +1,22 @@
|
||||||
using LinqToDB.Common;
|
using LinqToDB.Common;
|
||||||
using LinqToDB.EntityFrameworkCore;
|
using LinqToDB.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using EllieBot.Migrations;
|
using EllieBot.Migrations;
|
||||||
|
|
||||||
namespace EllieBot.Db;
|
namespace EllieBot.Db;
|
||||||
|
|
||||||
public sealed class EllieDbService : DbService
|
public sealed class EllieDbService : DbService
|
||||||
{
|
{
|
||||||
private readonly IBotCredsProvider _creds;
|
private readonly IBotCredsProvider _creds;
|
||||||
|
|
||||||
// these are props because creds can change at runtime
|
// these are props because creds can change at runtime
|
||||||
private string DbType => _creds.GetCreds().Db.Type.ToLowerInvariant().Trim();
|
private string DbType
|
||||||
private string ConnString => _creds.GetCreds().Db.ConnectionString;
|
=> _creds.GetCreds().Db.Type.ToLowerInvariant().Trim();
|
||||||
|
|
||||||
|
private string ConnString
|
||||||
|
=> _creds.GetCreds().Db.ConnectionString;
|
||||||
|
|
||||||
public EllieDbService(IBotCredsProvider creds)
|
public EllieDbService(IBotCredsProvider creds)
|
||||||
{
|
{
|
||||||
LinqToDBForEFTools.Initialize();
|
LinqToDBForEFTools.Initialize();
|
||||||
|
@ -28,14 +32,14 @@ public sealed class EllieDbService : DbService
|
||||||
|
|
||||||
await using var context = CreateRawDbContext(dbType, connString);
|
await using var context = CreateRawDbContext(dbType, connString);
|
||||||
|
|
||||||
await MigrationRunner.RunMigration(context);
|
await RunMigration(context);
|
||||||
|
|
||||||
// make sure sqlite db is in wal journal mode
|
// make sure sqlite db is in wal journal mode
|
||||||
if (context is SqliteContext)
|
if (context is SqliteContext)
|
||||||
{
|
{
|
||||||
await context.Database.ExecuteSqlRawAsync("PRAGMA journal_mode=WAL");
|
await context.Database.ExecuteSqlRawAsync("PRAGMA journal_mode=WAL");
|
||||||
}
|
}
|
||||||
|
|
||||||
// await context.Database.MigrateAsync();
|
// 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.");
|
throw new NotSupportedException($"The database provide type of '{dbType}' is not supported.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private EllieContext GetDbContextInternal()
|
private EllieContext GetDbContextInternal()
|
||||||
{
|
{
|
||||||
var dbType = DbType;
|
var dbType = DbType;
|
||||||
|
@ -74,4 +78,52 @@ public sealed class EllieDbService : DbService
|
||||||
|
|
||||||
public override EllieContext GetDbContext()
|
public override EllieContext GetDbContext()
|
||||||
=> GetDbContextInternal();
|
=> 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.");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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.");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,10 +8,6 @@ Write-Output "Creating new migration..."
|
||||||
# Step 1: Create initial migrations
|
# Step 1: Create initial migrations
|
||||||
dotnet build
|
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 SqliteContext --output-dir "Migrations/Sqlite" --no-build
|
||||||
dotnet ef migrations add $MigrationName --context PostgresqlContext --output-dir "Migrations/PostgreSql" --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
|
$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
|
$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 init $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 PostgresqlContext -o "Migrations/Postgresql/$newMigrationIdPostgresql.sql" --no-build
|
||||||
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
Write-Error "Error: Failed to generate SQL script"
|
Write-Error "Error: Failed to generate SQL script"
|
||||||
|
@ -53,5 +49,5 @@ dotnet build
|
||||||
|
|
||||||
# Step 4: Create new initial migrations
|
# Step 4: Create new initial migrations
|
||||||
Write-Output "Creating new initial migration..."
|
Write-Output "Creating new initial migration..."
|
||||||
dotnet ef migrations add $MigrationName --context SqliteContext --output-dir "Migrations/Sqlite" --no-build
|
dotnet ef migrations add init --context SqliteContext --output-dir "Migrations/Sqlite" --no-build
|
||||||
dotnet ef migrations add $MigrationName --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build
|
dotnet ef migrations add init --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build
|
|
@ -15,9 +15,6 @@ echo "Creating new migration..."
|
||||||
dotnet build
|
dotnet build
|
||||||
|
|
||||||
# Getting previous migration names in order to generate SQL scripts
|
# 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 SqliteContext --output-dir "Migrations/Sqlite" --no-build
|
||||||
dotnet ef migrations add "${MIGRATION_NAME}" --context PostgresqlContext --output-dir "Migrations/PostgreSql" --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_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)
|
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 init $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 PostgresqlContext -o "Migrations/Postgresql/${NEW_MIGRATION_ID_POSTGRESQL}.sql" --no-build
|
||||||
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
|
@ -78,8 +75,8 @@ for file in "Migrations/Postgresql"/*; do
|
||||||
done
|
done
|
||||||
|
|
||||||
# Step 4: Adding new initial migration
|
# Step 4: Adding new initial migration
|
||||||
|
echo "Creating new initial migration..."
|
||||||
|
|
||||||
dotnet build
|
dotnet build
|
||||||
echo "Creating new initial migration..."
|
dotnet ef migrations add init --context SqliteContext --output-dir "Migrations/Sqlite" --no-build
|
||||||
dotnet ef migrations add "${MIGRATION_NAME}" --context SqliteContext --output-dir "Migrations/Sqlite" --no-build
|
dotnet ef migrations add init --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build
|
||||||
dotnet ef migrations add "${MIGRATION_NAME}" --context PostgresqlContext --output-dir "Migrations/PostgreSql" --no-build
|
|
Loading…
Add table
Reference in a new issue