HangfireIO/Hangfire · error · MissingMemberException
Property '{type.FullName}.BatchCommand' not found.
Error message
Property '{type.FullName}.BatchCommand' not found. What it means
MissingMemberException thrown while resolving the BatchCommand property getter on SqlCommandSet via reflection (Instance|Public|NonPublic). The expression that reads the accumulated batch command cannot be compiled because the property is absent on the resolved type.
Source
Thrown at src/Hangfire.SqlServer/SqlCommandSet.cs:94
_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);
return Expression.Lambda<Func<object, DbCommand>>(Expression.Property(converted, batchCommandProperty), p).Compile();
});
_appendMethod = AppendMethod.GetOrAdd(sqlCommandSetType, type =>
{
var p = Expression.Parameter(typeof(object));
var converted = Expression.Convert(p, type);
var batchCommandParameter = Expression.Parameter(typeof(DbCommand));
return Expression.Lambda<Action<object, DbCommand>>(Expression.Call(converted, "Append", null, Expression.Convert(batchCommandParameter, batchCommandProperty.PropertyType)), p, batchCommandParameter).Compile();
});
_executeNonQueryMethod = ExecuteNonQueryMethod.GetOrAdd(sqlCommandSetType, static type =>
{
var p = Expression.Parameter(typeof(object));
var converted = Expression.Convert(p, type);View on GitHub (pinned to c236dd0f93)
Solutions
- Use a SqlClient + Hangfire.SqlServer version pair validated in the Hangfire.SqlServer compatibility matrix.
- Turn off assembly trimming/obfuscation that strips the property metadata.
- Open an issue / upgrade Hangfire.SqlServer if the provider legitimately renamed the member.
Example fix
// before <PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.0-preview" /> // after (use a stable, supported release) <PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
Defensive patterns
Strategy: type-guard
Validate before calling
static bool HasBatchCommandProperty(Type sqlCommandSetType)
=> sqlCommandSetType.GetProperty("BatchCommand",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null; Type guard
static bool IsSqlCommandSetUsable(Type type) =>
type.GetProperty("BatchCommand", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null; Prevention
- Pin SqlClient to a version documented compatible with your Hangfire.SqlServer release.
- Avoid preview/obfuscated SqlClient packages in production.
- Add a startup health check that probes the provider's batch surface.
When it happens
Trigger: A SqlClient assembly whose SqlCommandSet type does not expose a BatchCommand property under that name; provider renamed the property (e.g. to CommandCollection) or removed it.
Common situations: Provider major-version upgrade that refactored internal batching; trimming; using an unsupported fork of SqlClient.
Related errors
- Property '{type.FullName}.Connection' not found.
- Could not load type 'SqlCommandSet' from assembly '{sqlClien
- Property '{type.FullName}.Transaction' not found.
- SqlCommandSet for {connection.GetType().FullName} is not sup
- The type `{type.FullName}` does not contain a method with si
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/81d61b95c62bff2f.
Report an issue: GitHub.