HangfireIO/Hangfire · error · MissingMemberException

Property '{type.FullName}.Connection' not found.

Error message

Property '{type.FullName}.Connection' not found.

What it means

MissingMemberException thrown while building the expression to set the Connection property on the SqlCommandSet instance: GetProperty("Connection", Instance|Public|NonPublic) returned null for the resolved type. Hangfire reflects non-public members of the batch type; if the provider renamed or removed the Connection setter, the accessor cannot be compiled.

Source

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

                        // GitHub Issue: https://github.com/dotnet/corefx/issues/29391
                        throw new NotSupportedException(".NET Core version of the System.Data.SqlClient package below 4.7.0 (which has assembly version 4.6.0.0) doesn't properly implement the SqlCommandSet class.");
                    }

                    var type = sqlClientAssembly.GetTypes().FirstOrDefault(static x => x.Name == "SqlCommandSet");
                    if (type == null)
                    {
                        throw new TypeLoadException($"Could not load type 'SqlCommandSet' from assembly '{sqlClientAssembly}'.");
                    }

                    return type;
                });

                _setConnection = SetConnection.GetOrAdd(sqlCommandSetType, static type =>
                {
                    var p = Expression.Parameter(typeof(object));
                    var converted = Expression.Convert(p, type);
                    var connectionParameter = Expression.Parameter(typeof(DbConnection));
                    var connectionProperty = type.GetProperty("Connection", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new MissingMemberException($"Property '{type.FullName}.Connection' not found.");
                    return Expression.Lambda<Action<object, DbConnection>>(Expression.Assign(Expression.Property(converted, connectionProperty), Expression.Convert(connectionParameter, connectionProperty.PropertyType)), p, connectionParameter).Compile();
                });
                _setTransaction = SetTransaction.GetOrAdd(sqlCommandSetType, static type =>
                {
                    var p = Expression.Parameter(typeof(object));
                    var converted = Expression.Convert(p, type);
                    var transactionParameter = Expression.Parameter(typeof(DbTransaction));
                    var transactionProperty = type.GetProperty("Transaction", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new MissingMemberException($"Property '{type.FullName}.Transaction' not found.");
                    return Expression.Lambda<Action<object, DbTransaction>>(Expression.Assign(Expression.Property(converted, transactionProperty), Expression.Convert(transactionParameter, transactionProperty.PropertyType)), p, transactionParameter).Compile();
                });
                var batchCommandProperty = BatchCommandProperty.GetOrAdd(sqlCommandSetType, static type =>
                {
                    return type.GetProperty("BatchCommand", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new MissingMemberException($"Property '{type.FullName}.BatchCommand' not found.");
                });
                _getBatchCommand = GetBatchCommand.GetOrAdd(sqlCommandSetType, type =>
                {
                    var p = Expression.Parameter(typeof(object));
                    var converted = Expression.Convert(p, type);

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Use a SqlClient package version that is known compatible with your Hangfire.SqlServer version (check release notes).
  2. Avoid assembly trimming/obfuscation on the SqlClient assembly.
  3. Upgrade Hangfire.SqlServer to a release that supports the newer internal layout.

Example fix

// before
<PackageReference Include="Hangfire.SqlServer" Version="1.6.x" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.0.0" />

// after (align versions per Hangfire.SqlServer release notes)
<PackageReference Include="Hangfire.SqlServer" Version="1.8.x" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.x" />
Defensive patterns

Strategy: type-guard

Validate before calling

static bool HasConnectionProperty(Type sqlCommandSetType)
    => sqlCommandSetType.GetProperty("Connection",
        BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null;

Type guard

static bool IsSqlCommandSetUsable(Type type) =>
    type.GetProperty("Connection", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null;

Prevention

When it happens

Trigger: Using a SqlClient assembly whose SqlCommandSet type exists but no longer has a Connection property discoverable via reflection (renamed property, different visibility, obfuscation).

Common situations: Provider version change that altered internal property names; an obfuscated/trimmed assembly; using Microsoft.Data.SqlClient on a version where the internal surface differs.

Related errors


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