diff --git a/PolyTrader.App.csproj b/PolyTrader.App.csproj
index 5b762ff..c3ca23e 100644
--- a/PolyTrader.App.csproj
+++ b/PolyTrader.App.csproj
@@ -32,6 +32,11 @@
PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/Program.cs b/Program.cs
index 8309d27..d6951a1 100644
--- a/Program.cs
+++ b/Program.cs
@@ -48,6 +48,13 @@ internal static class Program
return;
}
+ // Diagnose: gibt die MySQL-Serverversion aus (für das ServerVersion-Pinning). Kein UI.
+ if (args.Length > 0 && string.Equals(args[0], "--db-version", StringComparison.OrdinalIgnoreCase))
+ {
+ RunDbVersion();
+ return;
+ }
+
ApplicationConfiguration.Initialize();
var modules = new System.Collections.Generic.List
@@ -56,6 +63,9 @@ internal static class Program
};
AppHost = Host.CreateDefaultBuilder()
+ // Config immer neben der EXE suchen (nicht im Arbeitsverzeichnis), damit die App
+ // auch beim Start aus bin/ oder per Doppelklick ihre appsettings findet.
+ .UseContentRoot(AppContext.BaseDirectory)
// Host.CreateDefaultBuilder lädt appsettings.Local.json NICHT (nur appsettings.json
// + appsettings.{Environment}.json). Die gitignorierte Local-Datei hält aber die
// MySQL-Connection – daher hier explizit ergänzen, sonst bleibt sie leer.
@@ -252,6 +262,34 @@ internal static class Program
Services.ConfigMigrator.VerifyMySql(mySql);
}
+ private static void RunDbVersion()
+ {
+ var config = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
+ .SetBasePath(System.IO.Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: true)
+ .AddJsonFile("appsettings.Local.json", optional: true)
+ .AddEnvironmentVariables()
+ .Build();
+
+ var conn = config["Database:MySqlConnectionString"] ?? string.Empty;
+ if (string.IsNullOrWhiteSpace(conn))
+ {
+ Console.WriteLine("FEHLER: Database:MySqlConnectionString fehlt (appsettings.Local.json).");
+ return;
+ }
+
+ try
+ {
+ using var c = new MySqlConnector.MySqlConnection(conn);
+ c.Open();
+ Console.WriteLine($"ServerVersion: {c.ServerVersion}");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"FEHLER: {ex.GetType().Name}: {ex.Message}");
+ }
+ }
+
///
/// Headless-Smoke-Test: baut einen minimalen Host (Persistenz + State + Modul-Registrierung
/// + Shell/Launcher), hydriert den State aus MySQL und konstruiert jede registrierte View
@@ -265,6 +303,7 @@ internal static class Program
var modules = new System.Collections.Generic.List { new CopyTradingModule() };
using var host = Host.CreateDefaultBuilder()
+ .UseContentRoot(AppContext.BaseDirectory)
.ConfigureAppConfiguration((context, config) =>
config.AddJsonFile("appsettings.Local.json", optional: true, reloadOnChange: false))
.ConfigureServices((context, services) =>
diff --git a/src/PolyTrader.Core/Configuration/DatabaseOptions.cs b/src/PolyTrader.Core/Configuration/DatabaseOptions.cs
index 7c074d1..7951631 100644
--- a/src/PolyTrader.Core/Configuration/DatabaseOptions.cs
+++ b/src/PolyTrader.Core/Configuration/DatabaseOptions.cs
@@ -1,3 +1,6 @@
+using System;
+using Microsoft.EntityFrameworkCore;
+
namespace PolyTrader.Core.Configuration
{
///
@@ -11,4 +14,15 @@ namespace PolyTrader.Core.Configuration
/// MySQL-Connection-String (aus gitignorierter appsettings.Local.json).
public string MySqlConnectionString { get; set; } = string.Empty;
}
+
+ ///
+ /// Feste Ziel-Server-Version (MariaDB 11.8.6, wie am Server erkannt). Bewusst gepinnt statt
+ /// ServerVersion.AutoDetect: AutoDetect öffnet beim Bau der DbContext-Optionen eine
+ /// blockierende DB-Verbindung – ist die DB langsam/nicht erreichbar, hängt/crasht der Start,
+ /// bevor die UI erscheint. Mit fester Version startet die App unabhängig von der DB.
+ ///
+ public static class DatabaseServerVersion
+ {
+ public static ServerVersion Value => new MariaDbServerVersion(new Version(11, 8, 6));
+ }
}
diff --git a/src/PolyTrader.Core/DependencyInjection/ServiceCollectionExtensions.cs b/src/PolyTrader.Core/DependencyInjection/ServiceCollectionExtensions.cs
index e863b43..40b99fd 100644
--- a/src/PolyTrader.Core/DependencyInjection/ServiceCollectionExtensions.cs
+++ b/src/PolyTrader.Core/DependencyInjection/ServiceCollectionExtensions.cs
@@ -17,7 +17,7 @@ namespace PolyTrader.Core.DependencyInjection
public static IServiceCollection AddCorePersistence(this IServiceCollection services, DatabaseOptions options)
{
var conn = options.MySqlConnectionString;
- services.AddDbContextFactory(o => o.UseMySql(conn, ServerVersion.AutoDetect(conn)));
+ services.AddDbContextFactory(o => o.UseMySql(conn, DatabaseServerVersion.Value));
services.AddSingleton();
services.AddSingleton();
diff --git a/src/PolyTrader.Modules.CopyTrading/CopyTradingModule.cs b/src/PolyTrader.Modules.CopyTrading/CopyTradingModule.cs
index 9699fb7..8e83513 100644
--- a/src/PolyTrader.Modules.CopyTrading/CopyTradingModule.cs
+++ b/src/PolyTrader.Modules.CopyTrading/CopyTradingModule.cs
@@ -5,6 +5,7 @@ using System.Threading.Channels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using PolyTrader.Core.Configuration;
using PolyTrader.Core.Modularity;
using PolyTrader.Modules.CopyTrading.Persistence;
using PolyTrader.Modules.CopyTrading.Persistence.Ef;
@@ -39,7 +40,7 @@ namespace PolyTrader.Modules.CopyTrading
// Modul-Persistenz: EF Core / Pomelo / MySQL (thread-safer DbContextFactory).
var conn = configuration["Database:MySqlConnectionString"] ?? string.Empty;
- services.AddDbContextFactory(o => o.UseMySql(conn, ServerVersion.AutoDetect(conn)));
+ services.AddDbContextFactory(o => o.UseMySql(conn, DatabaseServerVersion.Value));
services.AddSingleton();
services.AddSingleton();
diff --git a/src/PolyTrader.Modules.CopyTrading/Services/CopyTradingEngine.cs b/src/PolyTrader.Modules.CopyTrading/Services/CopyTradingEngine.cs
index eb30a0c..75a2a74 100644
--- a/src/PolyTrader.Modules.CopyTrading/Services/CopyTradingEngine.cs
+++ b/src/PolyTrader.Modules.CopyTrading/Services/CopyTradingEngine.cs
@@ -53,6 +53,7 @@ namespace PolyTraderSharp.Services
public override async Task StartAsync(CancellationToken cancellationToken)
{
_logger.Info("Starte Preload des MarketCache aus der Datenbank um Flaschenhälse zu vermeiden...");
+ try
{
// Initialize cache for EVERYTHING in DB that is not closed!
var activeMarkets = _marketRepo.GetActive();
@@ -62,7 +63,7 @@ namespace PolyTraderSharp.Services
{
if (!string.IsNullOrEmpty(md.ClobTokenIds))
{
- try
+ try
{
var tokenIds = System.Text.Json.JsonSerializer.Deserialize>(md.ClobTokenIds);
if (tokenIds != null)
@@ -79,6 +80,12 @@ namespace PolyTraderSharp.Services
}
_logger.Info($"MarketCache Preload abgeschlossen: {loaded} Token herangeführt.");
}
+ catch (Exception ex)
+ {
+ // DB nicht erreichbar o.ä.: Start NICHT abbrechen (sonst erscheint keine UI).
+ // Der Cache füllt sich zur Laufzeit über den MarketSync/Signale nach.
+ _logger.Error($"MarketCache Preload übersprungen (DB nicht erreichbar?): {ex.Message}");
+ }
await base.StartAsync(cancellationToken);
}
diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.resx b/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file