Validating Connection Strings on .NET Startup
Initial Host Configuration
using System.Data.Common; using Microsoft.Data.SqlClient; using Microsoft.Data.Sqlite; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using WorkerServiceDatabase; IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services // validate connection strings .ValidateConnectionStrings() .ValidateOnStart(); services.AddHostedService<Worker>(); }) .Build(); host.Run(); public static class ConnectionStringExtensions { public static OptionsBuilder<ConnectionStrings> ValidateConnectionStrings(this IServiceCollection services) { return services .AddOptions<ConnectionStrings>() .BindConfiguration("ConnectionStrings") .Validate(c => c.Validate(), "Could not connect to 1 or more databases."); } } public class ConnectionStrings : Dictionary<string,string> { public ConnectionStrings() { // these are the key names DbProviderFactories.RegisterFactory("Sqlite", SqliteFactory.Instance); DbProviderFactories.RegisterFactory("SqlServer", SqlClientFactory.Instance); } public bool Validate() { // can't inject logger :( var logger = LoggerFactory .Create(cfg => cfg.AddConsole().AddDebug()) .CreateLogger("ConnectionStrings"); List<Exception> errors = new(); foreach (var (key, connectionString) in this) { try { var factory = DbProviderFactories.GetFactory(key); using var connection = factory.CreateConnection(); if (connection is null) { throw new Exception($"\"{key}\" did not have a valid database provider registered"); } connection.ConnectionString = connectionString; connection.Open(); } catch (Exception e) { var message = $"Could not connect to \"{key}\"."; logger.LogError(message); errors.Add(new Exception(message, e)); } } return errors.IsNullOrEmpty(); } }
ConnectionString Configuration
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.Hosting.Lifetime": "Information" } }, "ConnectionStrings": { "Sqlite": "Data Source=database.db", "SqlServer": "Data Source=localhost,11433;Initial Catalog=DBName;User Id=sa;Password=password;Encrypt=false" } }