{"record":{"id":"a351a64fc42a7ddf","repo":"HangfireIO/Hangfire","slug":"could-not-load-type-sqlcommandset-from-assembly","errorCode":null,"errorMessage":"Could not load type 'SqlCommandSet' from assembly '{sqlClientAssembly}'.","messagePattern":"Could not load type 'SqlCommandSet' from assembly '(.+?)'\\.","errorType":"exception","errorClass":"TypeLoadException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.SqlServer/SqlCommandSet.cs","lineNumber":70,"sourceCode":"                sqlCommandSetType = SqlCommandSetType.GetOrAdd(connection.GetType().GetTypeInfo().Assembly, static sqlClientAssembly =>\n                {\n                    var assemblyName = sqlClientAssembly.GetName();\n                    var version = assemblyName.Version;\n\n                    if (assemblyName.Name == \"System.Data.SqlClient\" && Version.Parse(\"4.0.0.0\") < version && version < Version.Parse(\"4.6.0.0\"))\n                    {\n                        // .NET Core version of the System.Data.SqlClient package below 4.7.0 (which\n                        // has assembly version 4.6.0.0) doesn't properly implement the SqlCommandSet\n                        // class, throwing the following exception in run-time:\n                        // ArgumentException: Specified parameter name 'Parameter1' is not valid.\n                        // GitHub Issue: https://github.com/dotnet/corefx/issues/29391\n                        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.\");\n                    }\n\n                    var type = sqlClientAssembly.GetTypes().FirstOrDefault(static x => x.Name == \"SqlCommandSet\");\n                    if (type == null)\n                    {\n                        throw new TypeLoadException($\"Could not load type 'SqlCommandSet' from assembly '{sqlClientAssembly}'.\");\n                    }\n\n                    return type;\n                });\n\n                _setConnection = SetConnection.GetOrAdd(sqlCommandSetType, static type =>\n                {\n                    var p = Expression.Parameter(typeof(object));\n                    var converted = Expression.Convert(p, type);\n                    var connectionParameter = Expression.Parameter(typeof(DbConnection));\n                    var connectionProperty = type.GetProperty(\"Connection\", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new MissingMemberException($\"Property '{type.FullName}.Connection' not found.\");\n                    return Expression.Lambda<Action<object, DbConnection>>(Expression.Assign(Expression.Property(converted, connectionProperty), Expression.Convert(connectionParameter, connectionProperty.PropertyType)), p, connectionParameter).Compile();\n                });\n                _setTransaction = SetTransaction.GetOrAdd(sqlCommandSetType, static type =>\n                {\n                    var p = Expression.Parameter(typeof(object));\n                    var converted = Expression.Convert(p, type);\n                    var transactionParameter = Expression.Parameter(typeof(DbTransaction));","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.SqlServer/SqlCommandSet.cs#L52-L88","documentation":"TypeLoadException thrown by SqlCommandSet's type loader when no public/internal type named 'SqlCommandSet' can be found in the resolved sqlClient assembly via GetTypes().FirstOrDefault. This means the provider assembly either does not expose batch-command infrastructure at all or its layout differs from what Hangfire expects.","triggerScenarios":"Pointing Hangfire.SqlServer at a connection whose underlying provider assembly has no SqlCommandSet type (e.g. Microsoft.Data.SqlClient on a platform/version where the internal type was renamed, or a third-party provider).","commonSituations":"Switching from System.Data.SqlClient to Microsoft.Data.SqlClient where the batch type isn't located; using a provider stub or mocked DbConnection in tests; provider version that reorganized internal types.","solutions":["Use a supported Microsoft.Data.SqlClient / System.Data.SqlClient version that exposes the SqlCommandSet type Hangfire expects.","If using a custom/in-memory DbConnection in tests, disable batch inserts or provide a real provider connection.","Update Hangfire.SqlServer to a version compatible with your provider's type layout."],"exampleFix":"// before (test using a fake DbConnection)\nusing var conn = new FakeDbConnection();\n\n// after (use the real provider)\nusing var conn = new SqlConnection(connectionString);","handlingStrategy":"type-guard","validationCode":"static bool HasSqlCommandSetType(DbConnection connection)\n    => connection.GetType().Assembly.GetTypes().Any(t => t.Name == \"SqlCommandSet\");","typeGuard":"static bool SupportsBatchCommands(DbConnection connection) =>\n    connection.GetType().Assembly.GetTypes().Any(static t => t.Name == \"SqlCommandSet\");","tryCatchPattern":null,"preventionTips":["Use a supported SqlClient version; avoid custom/fake DbConnection in non-test code.","Keep Hangfire.SqlServer and SqlClient versions aligned per release notes.","Guard test fixtures so they skip batch-path tests when the provider lacks the type."],"tags":["sqlserver","reflection","provider","type-load"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}