using Microsoft.Extensions.Configuration; using System; using System.Threading; namespace XLAB2.Infrastructure; internal static class DatabaseConfiguration { private static readonly Lazy Options = new(LoadOptions, LazyThreadSafetyMode.ExecutionAndPublication); public static DatabaseOptions Current => Options.Value; private static DatabaseOptions LoadOptions() { var configuration = new ConfigurationBuilder() .SetBasePath(AppContext.BaseDirectory) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddEnvironmentVariables(prefix: "XLAB2_") .Build(); var options = configuration.GetSection("Database").Get() ?? new DatabaseOptions(); Validate(options); return options; } private static void Validate(DatabaseOptions options) { if (string.IsNullOrWhiteSpace(options.Server)) { throw new InvalidOperationException("Database:Server is required."); } if (string.IsNullOrWhiteSpace(options.Database)) { throw new InvalidOperationException("Database:Database is required."); } if (options.ConnectTimeoutSeconds <= 0) { throw new InvalidOperationException("Database:ConnectTimeoutSeconds must be greater than zero."); } if (options.CommandTimeoutSeconds <= 0) { throw new InvalidOperationException("Database:CommandTimeoutSeconds must be greater than zero."); } if (options.MinPoolSize < 0) { throw new InvalidOperationException("Database:MinPoolSize cannot be negative."); } if (options.MaxPoolSize <= 0) { throw new InvalidOperationException("Database:MaxPoolSize must be greater than zero."); } if (options.MinPoolSize > options.MaxPoolSize) { throw new InvalidOperationException("Database:MinPoolSize cannot be greater than Database:MaxPoolSize."); } if (options.ConnectRetryCount < 0) { throw new InvalidOperationException("Database:ConnectRetryCount cannot be negative."); } if (options.ConnectRetryIntervalSeconds < 1) { throw new InvalidOperationException("Database:ConnectRetryIntervalSeconds must be greater than zero."); } } }