using System; using System.Collections.Generic; using System.Linq; using c3stream.DataModels; using c3stream.DataModels.Tables; using LinqToDB; using LinqToDB.Data; namespace c3stream; public static class Migrations { private const int DbVer = 0; private static readonly List _migrations = new(); public static void RunMigrations() { using var db = new Database.DbConn(); var ccolor = Console.ForegroundColor; if (!db.DataProvider.GetSchemaProvider().GetSchema(db).Tables.Any()) { Console.ForegroundColor = ConsoleColor.DarkCyan; Console.Write("Running migration: "); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Initialize Database"); db.CreateTable(); db.CreateTable(); db.InsertWithIdentity(new DbInfo { DbVer = DbVer }); } else if (db.DataProvider.GetSchemaProvider().GetSchema(db).Tables.All(t => t.TableName != "DbInfo")) { db.CreateTable(); db.InsertWithIdentity(new DbInfo { DbVer = 0 }); } Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"Database version: {db.DbInfo.ToList().First().DbVer}"); var migrationsToRun = _migrations.FindAll(p => p.IntroducedWithDbVer > db.DbInfo.First().DbVer); if (migrationsToRun.Count == 0) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("No migrations to run."); } else { new Migration(0, "BEGIN TRANSACTION").Run(db); try { migrationsToRun.ForEach(p => p.Run(db)); } catch { Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine($"Migrating to database version {DbVer} failed."); new Migration(0, "ROLLBACK TRANSACTION").Run(db); Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine("Rolled back migrations."); Environment.Exit(1); } new Migration(0, "COMMIT TRANSACTION").Run(db); var newdb = new Database.DbConn(); var dbinfo = newdb.DbInfo.First(); dbinfo.DbVer = DbVer; newdb.Update(dbinfo); Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine($"Database version is now: {DbVer}"); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Finished running migrations."); } Console.ForegroundColor = ccolor; } private class Migration { private readonly string _sql; public readonly int IntroducedWithDbVer; public Migration(int introducedWithDbVer, string sql) { IntroducedWithDbVer = introducedWithDbVer; _sql = sql; } public void Run(DataConnection db) { Console.ForegroundColor = ConsoleColor.DarkCyan; Console.Write("Running migration: "); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(_sql); db.Execute(_sql); } } }