Add AppDbUpdater
This commit is contained in:
@ -11,6 +11,7 @@ using System.Windows.Threading;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows.Markup;
|
using System.Windows.Markup;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Elwig {
|
namespace Elwig {
|
||||||
public partial class App : Application {
|
public partial class App : Application {
|
||||||
@ -20,10 +21,23 @@ namespace Elwig {
|
|||||||
public static readonly string TempPath = Path.Combine(Path.GetTempPath(), "Elwig");
|
public static readonly string TempPath = Path.Combine(Path.GetTempPath(), "Elwig");
|
||||||
public static readonly Config Config = new(DataPath + "config.ini");
|
public static readonly Config Config = new(DataPath + "config.ini");
|
||||||
|
|
||||||
|
public static int VersionMajor { get; private set; }
|
||||||
|
public static int VersionMinor { get; private set; }
|
||||||
|
public static int VersionPatch { get; private set; }
|
||||||
|
public static string Version {
|
||||||
|
get => $"{VersionMajor}.{VersionMinor}.{VersionPatch}";
|
||||||
|
private set {
|
||||||
|
var p = value.Split(".").Select(p => int.Parse(p.Trim())).ToArray();
|
||||||
|
VersionMajor = p.ElementAtOrDefault(0);
|
||||||
|
VersionMinor = p.ElementAtOrDefault(1);
|
||||||
|
VersionPatch = p.ElementAtOrDefault(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string ZwstId { get; private set; }
|
public static string ZwstId { get; private set; }
|
||||||
public static string BranchName { get; private set; }
|
public static string BranchName { get; private set; }
|
||||||
public static int? BranchPlz { get; private set; }
|
public static int? BranchPlz { get; private set; }
|
||||||
public static string? BranchOrt { get; private set; }
|
public static string? BranchLocation { get; private set; }
|
||||||
public static string? BranchAddress { get; private set; }
|
public static string? BranchAddress { get; private set; }
|
||||||
public static string? BranchPhoneNr { get; private set; }
|
public static string? BranchPhoneNr { get; private set; }
|
||||||
public static string? BranchFaxNr { get; private set; }
|
public static string? BranchFaxNr { get; private set; }
|
||||||
@ -36,7 +50,7 @@ namespace Elwig {
|
|||||||
|
|
||||||
public App() : base() {
|
public App() : base() {
|
||||||
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
||||||
Directory.CreateDirectory(App.TempPath);
|
Directory.CreateDirectory(TempPath);
|
||||||
Directory.CreateDirectory(DataPath);
|
Directory.CreateDirectory(DataPath);
|
||||||
MainDispatcher = Dispatcher;
|
MainDispatcher = Dispatcher;
|
||||||
Scales = Array.Empty<IScale>();
|
Scales = Array.Empty<IScale>();
|
||||||
@ -56,14 +70,18 @@ namespace Elwig {
|
|||||||
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))
|
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))
|
||||||
);
|
);
|
||||||
|
|
||||||
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = new();
|
Version = typeof(App).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? "";
|
||||||
using (var ctx = new AppDbContext()) {
|
|
||||||
try {
|
try {
|
||||||
if (!ctx.Database.CanConnect()) {
|
AppDbUpdater.CheckDb();
|
||||||
MessageBox.Show($"Invalid Database:\n\n{Config.DatabaseFile}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error);
|
} catch (Exception e) {
|
||||||
|
MessageBox.Show($"Invalid Database:\n\n{e.Message}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
Shutdown();
|
Shutdown();
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = new();
|
||||||
|
using (var ctx = new AppDbContext()) {
|
||||||
branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Dest, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
|
branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Dest, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
|
||||||
try {
|
try {
|
||||||
Client = new(ctx);
|
Client = new(ctx);
|
||||||
@ -73,12 +91,7 @@ namespace Elwig {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
MessageBox.Show($"Invalid Database:\n\n{e.Message}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
Shutdown();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Utils.RunBackground("HTML Initialization", () => Documents.Html.Init(PrintingReadyChanged));
|
Utils.RunBackground("HTML Initialization", () => Documents.Html.Init(PrintingReadyChanged));
|
||||||
Utils.RunBackground("PDF Initialization", () => Documents.Pdf.Init(PrintingReadyChanged));
|
Utils.RunBackground("PDF Initialization", () => Documents.Pdf.Init(PrintingReadyChanged));
|
||||||
|
|
||||||
@ -114,7 +127,7 @@ namespace Elwig {
|
|||||||
ZwstId = entry.Item1;
|
ZwstId = entry.Item1;
|
||||||
BranchName = entry.Item2;
|
BranchName = entry.Item2;
|
||||||
BranchPlz = entry.Item3;
|
BranchPlz = entry.Item3;
|
||||||
BranchOrt = entry.Item4;
|
BranchLocation = entry.Item4;
|
||||||
BranchAddress = entry.Item5;
|
BranchAddress = entry.Item5;
|
||||||
BranchPhoneNr = entry.Item6;
|
BranchPhoneNr = entry.Item6;
|
||||||
BranchFaxNr = entry.Item7;
|
BranchFaxNr = entry.Item7;
|
||||||
@ -125,7 +138,7 @@ namespace Elwig {
|
|||||||
ZwstId = entry.Item1;
|
ZwstId = entry.Item1;
|
||||||
BranchName = entry.Item2;
|
BranchName = entry.Item2;
|
||||||
BranchPlz = entry.Item3;
|
BranchPlz = entry.Item3;
|
||||||
BranchOrt = entry.Item4;
|
BranchLocation = entry.Item4;
|
||||||
BranchAddress = entry.Item5;
|
BranchAddress = entry.Item5;
|
||||||
BranchPhoneNr = entry.Item6;
|
BranchPhoneNr = entry.Item6;
|
||||||
BranchFaxNr = entry.Item7;
|
BranchFaxNr = entry.Item7;
|
||||||
|
@ -13,7 +13,7 @@ namespace Elwig.Documents {
|
|||||||
|
|
||||||
public BusinessDocument(string title, Member m, bool includeSender = false) : base(title) {
|
public BusinessDocument(string title, Member m, bool includeSender = false) : base(title) {
|
||||||
Member = m;
|
Member = m;
|
||||||
Location = App.BranchName;
|
Location = App.BranchLocation;
|
||||||
IncludeSender = includeSender;
|
IncludeSender = includeSender;
|
||||||
var uid = (m.UstIdNr ?? "-") + (m.IsBuchführend ? "" : " <i>(pauschaliert)</i>");
|
var uid = (m.UstIdNr ?? "-") + (m.IsBuchführend ? "" : " <i>(pauschaliert)</i>");
|
||||||
Aside = $"<table><colgroup><col span='1' style='width: 22.5mm;'/><col span='1' style='width: 42.5mm;'/></colgroup>" +
|
Aside = $"<table><colgroup><col span='1' style='width: 22.5mm;'/><col span='1' style='width: 42.5mm;'/></colgroup>" +
|
||||||
|
78
Elwig/Helpers/AppDbUpdater.cs
Normal file
78
Elwig/Helpers/AppDbUpdater.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Elwig.Helpers {
|
||||||
|
public static class AppDbUpdater {
|
||||||
|
|
||||||
|
public static readonly int RequiredSchemaVersion = 1;
|
||||||
|
|
||||||
|
private static int _versionOffset = 0;
|
||||||
|
private static readonly Action<SqliteConnection>[] _updaters = new[] {
|
||||||
|
UpdateDbSchema_1_To_2, UpdateDbSchema_2_To_3
|
||||||
|
};
|
||||||
|
|
||||||
|
private static void ExecuteNonQuery(SqliteConnection cnx, string sql) {
|
||||||
|
using var cmd = cnx.CreateCommand();
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object? ExecuteScalar(SqliteConnection cnx, string sql) {
|
||||||
|
using var cmd = cnx.CreateCommand();
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
return cmd.ExecuteScalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string CheckDb() {
|
||||||
|
using var cnx = AppDbContext.Connect();
|
||||||
|
|
||||||
|
var applId = (long?)ExecuteScalar(cnx, "PRAGMA application_id") ?? 0;
|
||||||
|
if (applId != 0x454C5747) throw new Exception("Invalid application_id of database");
|
||||||
|
|
||||||
|
var schemaVers = (long?)ExecuteScalar(cnx, "PRAGMA schema_version") ?? 0;
|
||||||
|
_versionOffset = (int)(schemaVers % 100);
|
||||||
|
if (_versionOffset != 0) {
|
||||||
|
// schema was modified manually/externally
|
||||||
|
// TODO issue warning
|
||||||
|
}
|
||||||
|
UpdateDbSchema(cnx, (int)(schemaVers / 100), RequiredSchemaVersion);
|
||||||
|
|
||||||
|
var userVers = (long?)ExecuteScalar(cnx, "PRAGMA user_version") ?? 0;
|
||||||
|
var major = userVers >> 24;
|
||||||
|
var minor = (userVers >> 16) & 0xFF;
|
||||||
|
var patch = userVers & 0xFFFF;
|
||||||
|
|
||||||
|
if (App.VersionMajor > major || App.VersionMinor > minor || App.VersionPatch > patch) {
|
||||||
|
long vers = (App.VersionMajor << 24) | (App.VersionMinor << 16) | App.VersionPatch;
|
||||||
|
ExecuteNonQuery(cnx, $"PRAGMA user_version = {vers}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{major}.{minor}.{patch}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateDbSchema(SqliteConnection cnx, int fromVersion, int toVersion) {
|
||||||
|
if (fromVersion == toVersion) {
|
||||||
|
return;
|
||||||
|
} else if (fromVersion > toVersion) {
|
||||||
|
throw new Exception("schema_version of database is too new");
|
||||||
|
} else if (toVersion - 1 > _updaters.Length) {
|
||||||
|
throw new Exception("Unable to update database schema: Updater not implemented");
|
||||||
|
} else if (fromVersion <= 0) {
|
||||||
|
throw new Exception("schema_version of database is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecuteNonQuery(cnx, "PRAGMA locking_mode = EXCLUSIVE");
|
||||||
|
ExecuteNonQuery(cnx, "BEGIN EXCLUSIVE");
|
||||||
|
for (int i = fromVersion; i < toVersion; i++) {
|
||||||
|
_updaters[i - 1](cnx);
|
||||||
|
}
|
||||||
|
ExecuteNonQuery(cnx, "COMMIT");
|
||||||
|
ExecuteNonQuery(cnx, "VACUUM");
|
||||||
|
ExecuteNonQuery(cnx, $"PRAGMA schema_version = {toVersion * 100 + _versionOffset}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateDbSchema_1_To_2(SqliteConnection cnx) { }
|
||||||
|
|
||||||
|
private static void UpdateDbSchema_2_To_3(SqliteConnection cnx) { }
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user