diff --git a/DataModels/Database.cs b/DataModels/Database.cs index 5c17a7c..08bb14e 100644 --- a/DataModels/Database.cs +++ b/DataModels/Database.cs @@ -5,30 +5,31 @@ using LinqToDB; using LinqToDB.Configuration; using LinqToDB.Data; -namespace c3stream.DataModels { - public class Database { - public class ConnectionStringSettings : IConnectionStringSettings { - public string ConnectionString { get; set; } - public string Name { get; set; } - public string ProviderName { get; set; } - public bool IsGlobal => false; - } +namespace c3stream.DataModels; - public class Settings : ILinqToDBSettings { - public IEnumerable DataProviders => Enumerable.Empty(); +public class Database { + public class ConnectionStringSettings : IConnectionStringSettings { + public string ConnectionString { get; set; } + public string Name { get; set; } + public string ProviderName { get; set; } + public bool IsGlobal => false; + } - public string DefaultConfiguration => "SQLite"; - public string DefaultDataProvider => "SQLite"; + public class Settings : ILinqToDBSettings { + public IEnumerable DataProviders => Enumerable.Empty(); - public IEnumerable ConnectionStrings { - get { yield return new ConnectionStringSettings {Name = "db", ProviderName = "SQLite", ConnectionString = @"Data Source=data/c3stream.sqlite;"}; } - } - } + public string DefaultConfiguration => "SQLite"; + public string DefaultDataProvider => "SQLite"; - public class DbConn : DataConnection { - public DbConn() : base("db") { } - - public ITable States => GetTable(); + public IEnumerable ConnectionStrings { + get { yield return new ConnectionStringSettings { Name = "db", ProviderName = "SQLite", ConnectionString = @"Data Source=data/c3stream.sqlite;" }; } } } + + public class DbConn : DataConnection { + public DbConn() : base("db") { } + + public ITable States => GetTable(); + public ITable DbInfo => GetTable(); + } } \ No newline at end of file diff --git a/DataModels/Tables/DbInfo.cs b/DataModels/Tables/DbInfo.cs new file mode 100644 index 0000000..16b520c --- /dev/null +++ b/DataModels/Tables/DbInfo.cs @@ -0,0 +1,9 @@ +using LinqToDB.Mapping; + +namespace c3stream.DataModels.Tables; + +[Table(Name = "DbInfo")] +public class DbInfo { + [Column(Name = "ID"), PrimaryKey, Identity, NotNull] public int Id { get; set; } + [Column(Name = "DbVer"), NotNull] public int DbVer { get; set; } +} \ No newline at end of file diff --git a/Migrations.cs b/Migrations.cs new file mode 100644 index 0000000..794f2b5 --- /dev/null +++ b/Migrations.cs @@ -0,0 +1,90 @@ +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); + } + } +} \ No newline at end of file diff --git a/c3stream.csproj b/c3stream.csproj index 12b0386..21d6354 100644 --- a/c3stream.csproj +++ b/c3stream.csproj @@ -7,36 +7,36 @@ - - - + + + - <_ContentIncludedByDefault Remove="data\database.json" /> - <_ContentIncludedByDefault Remove="data\_c3stream.json" /> - <_ContentIncludedByDefault Remove="data\33c3.json" /> - <_ContentIncludedByDefault Remove="data\34c3.json" /> - <_ContentIncludedByDefault Remove="data\35c3.json" /> + <_ContentIncludedByDefault Remove="data\database.json"/> + <_ContentIncludedByDefault Remove="data\_c3stream.json"/> + <_ContentIncludedByDefault Remove="data\33c3.json"/> + <_ContentIncludedByDefault Remove="data\34c3.json"/> + <_ContentIncludedByDefault Remove="data\35c3.json"/> - + - + - + - + - +