SQL Server 2017创建System.Net.Http CLR程序集失败问题求助
问题根因
- 从
Reference Assemblies目录提取的dll是开发编译专用的元数据占位文件,不包含实际可执行IL代码,CLR验证时必然触发Code size is zero错误,这类文件本身无法部署到运行环境。 - SQL Server CLR宿主内置了系统程序集版本白名单和绑定策略,直接加载.NET Framework 4.7.2版本的高优先级系统dll会被策略拦截,触发
existing policy would keep it from being used报错。 - 从
Framework64\v4.0.30319根目录取的System.Net.Http是.NET 4.0 RTM基础版本,和项目编译时依赖的高版本程序集签名哈希不匹配,运行时会判定GAC与数据库内存储的程序集签名不一致,抛出0x80131050错误。 - 之前创建证书时提示证书过期,是因为所用dll的数字签名对应的证书已经失效,这种授权方式本身对系统核心程序集无效。
可行解决方案
方案一:直接从GAC加载受信任程序集(优先选用,稳定性最高)
- 先清理之前创建的错误配置,避免残留冲突:
-- 先删除依赖该程序集的自定义存储过程、函数、类型等对象 IF EXISTS (SELECT * FROM sys.assemblies WHERE name = 'System.Net.Http') DROP ASSEMBLY [System.Net.Http]; IF EXISTS (SELECT * FROM sys.server_principals WHERE name = 'MS.NETcer') DROP LOGIN [MS.NETcer]; IF EXISTS (SELECT * FROM sys.certificates WHERE name = 'MS.NETcer' AND parent_class_desc = 'SERVER') DROP CERTIFICATE [MS.NETcer];
- SQL Server 2017默认信任GAC中注册的合规.NET系统程序集,不需要手动上传本地dll,直接执行以下语句创建即可:
CREATE ASSEMBLY [System.Net.Http] FROM N'GAC' WITH PERMISSION_SET = UNSAFE;
执行该语句需要实例级
ALTER ANY ASSEMBLY权限,且SQL Server服务账号需有权限访问服务器本地GAC存储。
- 程序集创建完成后,重新部署业务CLR项目dll即可,不需要单独为System.Net.Http配置证书授权。
方案二:GAC加载失败时手动匹配正确版本部署
部分精简安装的SQL Server环境可能缺失GAC绑定配置,可按以下步骤操作:
- 登录SQL Server服务器本地,通过PowerShell查询当前运行环境实际加载的System.Net.Http文件路径,禁止使用开发机上拷贝的文件:
[System.Reflection.Assembly]::LoadWithPartialName("System.Net.Http").Location
- 复制上述命令返回路径下的dll文件到部署用共享盘符,不要使用Reference Assemblies目录、v4.0.30319根目录下的文件,也不要使用其他版本的dll。
- 关闭数据库的TRUSTWORTHY属性(该属性存在较高安全风险,不建议长期开启),改用正规证书签名授权:
-- 替换为你的实际业务数据库名 ALTER DATABASE [DataRobot] SET TRUSTWORTHY OFF; CREATE CERTIFICATE [MS.NETcer] FROM EXECUTABLE FILE = '共享盘路径\从服务器GAC复制的System.Net.Http.dll'; CREATE LOGIN [MS.NETcer] FROM CERTIFICATE [MS.NETcer]; GRANT UNSAFE ASSEMBLY TO [MS.NETcer]; CREATE ASSEMBLY [System.Net.Http] FROM '共享盘路径\从服务器GAC复制的System.Net.Http.dll' WITH PERMISSION_SET = UNSAFE;
- 对自有业务dll做相同的证书签名授权后,再创建关联的存储过程即可。
避坑提示
- 禁止跨机器复制.NET系统dll,系统dll会跟随Windows补丁更新,不同设备上同版本号的dll可能存在签名差异,必须使用SQL Server服务器本地GAC中存储的文件。
- Reference Assemblies目录下的所有文件仅用于开发时的编译引用,没有运行逻辑,不能用于生产部署。
- 不要通过修改注册表、开启全局CLR验证跳过等方式绕过安全检查,会导致后续CLR运行时出现随机崩溃、权限泄露等问题。
内容的提问来源于stack exchange,提问作者Jon Nguyen
相关产品推荐
相关产品推荐

