using IBKRTrader.Core.Settings; using MySqlConnector; namespace IBKRTrader.Core.Configuration; /// /// Die eine maßgebliche Datenbankverbindung der Anwendung – aufgelöst aus den beiden Quellen, /// die es historisch gab. /// /// Bisher lasen EF-Kontexte den Connection-String aus appsettings(.Local).json, /// während BackupWorker und die Versionsdiagnose Host/Port/Datenbank/Benutzer aus /// settings.json nahmen. Nichts erzwang, dass beide dasselbe meinen: eine Installation /// konnte monatelang sauber laufen und dabei eine Datenbank sichern, die es gar nicht gibt. /// /// Regel: Ist in der Konfiguration ein Connection-String hinterlegt, ist er /// maßgeblich und alles Weitere wird aus ihm abgeleitet. Fehlt er, wird die Verbindung aus /// settings.json gebaut – dann sind beide Quellen zwangsläufig deckungsgleich. /// public sealed class DatabaseEndpoint { public string ConnectionString { get; } public string Host { get; } public int Port { get; } public string Database { get; } public string User { get; } public string Password { get; } /// Woher die maßgebliche Verbindung stammt – für die Startmeldung. public string Source { get; } private DatabaseEndpoint(string connectionString, string source) { ConnectionString = connectionString; Source = source; var b = new MySqlConnectionStringBuilder(connectionString); Host = b.Server; Port = (int)b.Port; Database = b.Database; User = b.UserID; Password = b.Password; } /// /// Löst die maßgebliche Verbindung auf. Ein unlesbarer Connection-String fällt auf /// settings.json zurück, statt den Start zu verhindern – sichtbar wird das über /// und die Startprüfung. /// public static DatabaseEndpoint Resolve(string? configuredConnectionString, DatabaseSettings settings) { if (!string.IsNullOrWhiteSpace(configuredConnectionString)) { try { return new DatabaseEndpoint(configuredConnectionString, "appsettings"); } catch (Exception ex) { return new DatabaseEndpoint(settings.BuildConnectionString(), $"settings.json (Connection-String unlesbar: {ex.Message})"); } } return new DatabaseEndpoint(settings.BuildConnectionString(), "settings.json"); } /// /// Beschreibt eine Abweichung zwischen der maßgeblichen Verbindung und dem, was in /// settings.json steht – sonst null. Beides darf existieren, aber wer sie /// auseinanderlaufen lässt, sichert die falsche Datenbank. /// public string? DescribeDivergence(DatabaseSettings settings) { if (Source != "appsettings") return null; var differs = !string.Equals(Host, settings.Host, StringComparison.OrdinalIgnoreCase) || !string.Equals(Database, settings.Database, StringComparison.OrdinalIgnoreCase) || Port != settings.Port; return differs ? $"Datenbank-Konfiguration weicht ab: maßgeblich ist {this} (appsettings), " + $"settings.json nennt {settings}. Es gilt die maßgebliche Verbindung." : null; } /// Benutzer@Host:Port/Datenbank – nie das Passwort. public override string ToString() => $"{User}@{Host}:{Port}/{Database}"; }