I see you have already applied `using` to the transaction.

But given that a new `SqlConnection` is created for each command, I would suggest wrapping it in a `using` statement as well. 


    private async Task<T> CommandAsync<T>(Func<IDbConnection, IDbTransaction, int, Task<T>> command)
    {
        using(var connection = new SqlConnection(_connectionStrings.CurrentValue.MainDatabase))
        {
            await connection.OpenAsync().ConfigureAwait(false);
            using var transaction = await connection.BeginTransactionAsync();
            try
            {
                T result = await command(connection, transaction, 300).ConfigureAwait(false);
    
                await transaction.CommitAsync().ConfigureAwait(false);
    
                return result;
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync().ConfigureAwait(false);
                _logger.LogError(ex, "Rolled back transaction");
                throw;
            }
        }
    }