using Microsoft.Data.SqlClient; namespace ZB.MOM.WW.Secrets.Replicator.SqlServer; /// /// Opens connections to the shared SQL-Server secret database and carries the settings every /// command needs (schema name, command timeout). /// /// The validated SQL-Server store options. public sealed class SecretsSqlServerConnectionFactory(SqlServerSecretsOptions options) { private readonly SqlServerSecretsOptions _options = options ?? throw new ArgumentNullException(nameof(options)); /// The bracket-quoted, allow-list-validated schema prefix for object names. public string SchemaName => _options.SchemaName; /// Command timeout, in whole seconds, for every command issued against this store. public int CommandTimeoutSeconds => Math.Max(1, (int)_options.CommandTimeout.TotalSeconds); /// Opens a connection to the shared secret database. /// A token to cancel the connect. /// An opened connection. The caller owns disposal. public async Task OpenConnectionAsync(CancellationToken cancellationToken) { var connection = new SqlConnection(_options.ConnectionString); try { await connection.OpenAsync(cancellationToken).ConfigureAwait(false); return connection; } catch { await connection.DisposeAsync().ConfigureAwait(false); throw; } } /// /// Creates a command on with the configured timeout applied. /// /// The open connection. /// The command text. /// The ambient transaction, if any. /// The configured command. The caller owns disposal. public SqlCommand CreateCommand( SqlConnection connection, string commandText, SqlTransaction? transaction = null) { ArgumentNullException.ThrowIfNull(connection); SqlCommand command = connection.CreateCommand(); command.CommandText = commandText; command.CommandTimeout = CommandTimeoutSeconds; command.Transaction = transaction; return command; } }