HangfireIO/Hangfire · error · NotSupportedException

SqlCommandSet for {connection.GetType().FullName} is not sup

Error message

SqlCommandSet for {connection.GetType().FullName} is not supported, use regular commands instead

What it means

NotSupportedException thrown by the SqlCommandSet constructor's catch-all: any reflection/setup exception (TypeLoadException, MissingMemberException, etc.) while probing the provider's batch type is wrapped here with the connection's full type name, directing you to fall back to regular (non-batched) commands. It is the umbrella error for 'this provider can't be used for batched inserts'.

Source

Thrown at src/Hangfire.SqlServer/SqlCommandSet.cs:129

                    var p = Expression.Parameter(typeof(object));
                    var converted = Expression.Convert(p, type);
                    return Expression.Lambda<Func<object, int>>(Expression.Call(converted, "ExecuteNonQuery", null), p).Compile();
                });
                _disposeMethod = DisposeMethod.GetOrAdd(sqlCommandSetType, static type =>
                {
                    var p = Expression.Parameter(typeof(object));
                    var converted = Expression.Convert(p, type);
                    return Expression.Lambda<Action<object>>(Expression.Call(converted, "Dispose", null), p).Compile();
                });
                _constructor = SqlCommandSetConstructor.GetOrAdd(sqlCommandSetType, static type =>
                {
                    var ctor = Expression.New(type);
                    return Expression.Lambda<Func<object>>(ctor).Compile();
                });
            }
            catch (Exception exception) when (exception.IsCatchableExceptionType())
            {
                throw new NotSupportedException($"SqlCommandSet for {connection.GetType().FullName} is not supported, use regular commands instead", exception);
            }

            _instance = _constructor();
        }

        public DbConnection Connection
        {
            set => _setConnection(_instance, value);
        }

        public DbTransaction Transaction
        {
            set => _setTransaction(_instance, value);
        }

        public DbCommand BatchCommand => _getBatchCommand(_instance);
        public int CommandCount { get; private set; }

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Read the InnerException to find the exact reflection failure (type missing, property missing, etc.) and address that specifically.
  2. Switch to a supported Microsoft.Data.SqlClient / System.Data.SqlClient version and disable trimming.
  3. If the provider is genuinely unsupported, configure Hangfire to use regular (non-batch) command execution if such an option is available, or replace the test fake with a real provider connection.

Example fix

// before (fake connection in integration test)
var conn = new FakeDbConnection();
using var batch = new SqlCommandSet(conn); // -> NotSupportedException

// after
var conn = new SqlConnection(realConnectionString);
conn.Open();
using var batch = new SqlCommandSet(conn);
Defensive patterns

Strategy: try-catch

Validate before calling

static bool ProviderSupportsBatch(DbConnection conn)
{
    try
    {
        var t = conn.GetType().Assembly.GetTypes().FirstOrDefault(x => x.Name == "SqlCommandSet");
        if (t == null) return false;
        foreach (var p in new[] { "Connection", "Transaction", "BatchCommand" })
            if (t.GetProperty(p, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) == null)
                return false;
        return true;
    }
    catch { return false; }
}

Try / catch

try
{
    using var batch = new SqlCommandSet(connection);
}
catch (NotSupportedException ex)
{
    logger.Warn(ex.InnerException, "Falling back to regular commands for {Conn}", connection.GetType().FullName);
    // execute commands individually
}

Prevention

When it happens

Trigger: Constructing SqlCommandSet for a DbConnection whose provider fails any of the reflection steps (type load, property binding, delegate compilation); common with an unsupported/trimmed/incompatible provider.

Common situations: Incompatible SqlClient version, trimmed publish, a mocked/fake DbConnection in tests, or a third-party provider that does not mirror SqlClient's internal SqlCommandSet.

Related errors


AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13). Data as JSON: /api/errors/9c8ad98b670c7a83. Report an issue: GitHub.