Microsoft.Data.SqlClient 7.0.0 创建 ServerConnection 报错
结论
这是 Microsoft.Data.SqlClient 7.0.0 与当前版本的 Microsoft.SqlServer.SqlManagementObjects 存在二进制兼容问题。建议先将 Microsoft.Data.SqlClient 固定在已经验证可用的 6.1.4。等 Microsoft.SqlServer.SqlManagementObjects 发布明确兼容 7.0.0 的版本后,再同时升级这两个包。
修改连接字符串、认证方式或 ServerConnection 的 VB.NET 写法通常解决不了这个错误。程序集绑定重定向也无法补充 DLL 中不存在的类型。
原因
异常发生在这条语句中:
oCONServerConnection =
New Microsoft.SqlServer.Management.Common.ServerConnection(sqlConnection:=oCONSQL)
此时 SqlConnection 已经成功打开,因此数据库地址、用户名、密码和 TLS 设置并非本次异常的直接原因。
创建 ServerConnection 时,SMO 会加载并检查 Microsoft.Data.SqlClient 中的相关类型。当前版本的 SMO 仍然需要:
Microsoft.Data.SqlClient.SqlAuthenticationMethod
运行时实际加载的是 Microsoft.Data.SqlClient, Version=7.0.0.0,其中缺少 SMO 所需的这个类型或兼容的类型定义,CLR 因而抛出 TypeLoadException。
这是程序集 API 或二进制契约不匹配导致的类型加载错误,与普通的数据库连接失败不同。
立即恢复运行
如果升级前使用 6.1.4 时可以正常运行,可先回退并固定到该版本。
在 Package Manager Console 中执行:
Update-Package Microsoft.Data.SqlClient -Version 6.1.4
如果项目使用 PackageReference,可在项目文件中固定版本:
<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient"
Version="6.1.4" />
</ItemGroup>
一个解决方案中可能有多个项目直接或间接引用 Microsoft.Data.SqlClient,需要逐一检查。否则,部分项目可能使用 6.1.4,另一些项目仍会把 7.0.0 复制到输出目录。
可在 Package Manager Console 中查看已安装的相关包:
Get-Package Microsoft.Data.SqlClient
Get-Package Microsoft.SqlServer.SqlManagementObjects
回退后,按以下步骤处理:
- 清理解决方案。
- 确认输出目录中没有遗留的 7.0.0 程序集。
- 重新还原 NuGet 包并生成解决方案。
- 检查最终输出目录实际加载的
Microsoft.Data.SqlClient.dll版本。
不需要为此改写原有业务代码:
Using sqlConnection As New Microsoft.Data.SqlClient.SqlConnection(sConnectionString)
sqlConnection.Open()
If sqlConnection.State = ConnectionState.Open Then
Using serverConnection As New Microsoft.SqlServer.Management.Common.ServerConnection(
sqlConnection:=sqlConnection)
' 执行 SQL 脚本
End Using
End If
End Using
这里的 Using 用于释放资源,与修复类型加载错误无关。解决问题的办法是使用相互兼容的 NuGet 包版本。
后续如何升级
可以继续使用新版依赖,但应把 Microsoft.Data.SqlClient 和 Microsoft.SqlServer.SqlManagementObjects 作为一组依赖进行验证,避免只升级其中一个。
后续可按以下步骤操作:
- 查看
Microsoft.SqlServer.SqlManagementObjects的发行说明,确认其中明确支持Microsoft.Data.SqlClient 7.x。 - 确认该版本仍支持目标框架
.NET Framework 4.8。 - 在测试环境中同时升级两个包。
- 验证
SqlConnection.Open()、ServerConnection创建、脚本批次执行和认证方式。 - 测试通过后再部署到生产环境。
现有信息只能确认两个包存在兼容问题,无法证明某个尚未验证的 SMO 版本已经修复。因此,即使 SMO 发布了新版本,也应先确认它是否兼容 SqlClient 7.0.0。
为什么绑定重定向通常无效
.NET Framework 项目经常通过 app.config 中的 bindingRedirect 处理程序集版本冲突,例如:
<dependentAssembly>
<assemblyIdentity name="Microsoft.Data.SqlClient"
publicKeyToken="23ec7fc2d6eaa4a5"
culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0"
newVersion="7.0.0.0" />
</dependentAssembly>
绑定重定向只能指定要加载的程序集版本,无法在 7.0.0 中恢复 SMO 所需的 SqlAuthenticationMethod 类型。将所有旧版本引用强制重定向到 7.0.0,可能会让这个异常稳定复现。
只有确认目标程序集保留了兼容 API 后,才能使用绑定重定向处理版本号差异。
其他注意事项
修改 uid、pwd、Authentication 或 TrustServerCertificate 无法绕过该异常。错误发生在 SMO 创建包装连接期间,与 SQL Server 是否接受登录分属不同环节。
连接字符串中的密码不宜直接写入源码或配置仓库,可以改用受保护的配置、环境变量或合适的密钥管理服务。TrustServerCertificate=True 会跳过服务器证书链验证,是否保留需要根据部署环境和证书配置单独评估。该设置与本次 TypeLoadException 无关。
在官方兼容版本发布并通过项目验证前,可以将 Microsoft.Data.SqlClient 固定在 6.1.4。依赖管理需要使用最新且相互兼容的版本组合,无须让每个包都单独保持在最高版本。
备注:内容仅供参考。
