using Microsoft.Data.SqlClient; namespace ZB.MOM.WW.Auth.ApiKeys.SqlServer; /// /// Opens connections to the shared SQL Server API-key database and carries the settings every /// command needs (schema name, command timeout). /// /// The SQL Server API-key store options; validated in the constructor. /// is not usable. public sealed class AuthSqlServerConnectionFactory(SqlServerApiKeyOptions options) { private readonly SqlServerApiKeyOptions _options = Validate(options); private static SqlServerApiKeyOptions Validate(SqlServerApiKeyOptions options) { ArgumentNullException.ThrowIfNull(options); options.Validate(); return options; } /// The schema that owns the three API-key tables. public string Schema => _options.Schema; /// 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 API-key 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; } }