本文可帮助你解决在已从 SQL Server 不同实例移动的数据库上使用 CLR 对象时可能发生的两个不同的问题。
原始产品版本:SQL Server
原始 KB 编号: 918040
现象
请考虑以下场景。 分离或备份 SQL Server 实例中的数据库。 SQL Server 的实例在服务器 A 上运行。稍后,可将该数据库附加到或还原到在服务器 B 上运行的 SQL Server 实例。在这种情况下,可能会遇到以下症状:
尝试从服务器 B 上的数据库运行具有
external_access
或不安全权限集的现有公共语言运行时 (CLR) 对象时,会收到以下错误消息:Msg 10314,级别 16,状态 11,第 2 行
尝试加载程序集 ID 65536 时,Microsoft .NET Framework 中出错。 服务器可能资源不足,或者不信任该程序集,因为它的 PERMISSION_SET 设置为 EXTERNAL_ACCESS 或 UNSAFE。 请重新运行查询,或检查有关的文档了解如何解决程序集信任问题。 有关此错误的详细信息:
System.IO.FileLoadException:无法加载文件或程序集“AssemblyName,Version=0.0.0.0,Culture=neutral,PublicKeyToken=null”或其依赖项之一。 发生与安全相关的错误。 (HRESULT 异常:0x8013150A)System.IO.FileLoadException:
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark&stackMark, boolean forIntrospection) at System.Reflection.Assembly.Load(String assemblyString)尝试在同一数据库中创建具有
external_access
或不安全权限集的新程序集时,会收到以下错误消息:服务器:Msg 10327、级别 14、状态 1、第 1 行
程序集“AssemblyName”的 CREATE ASSEMBLY 失败,因为程序集“AssemblyName”未授权PERMISSION_SET = EXTERNAL_ACCESS。 当下列任一项为 true 时,将授权该程序集:数据库所有者(DBO)具有 EXTERNAL ACCESS ASSEMBLY 权限,并且该数据库具有 TRUSTWORTHY 数据库属性;或程序集使用具有 EXTERNAL ACCESS ASSEMBLY 权限的相应登录名的证书或非对称密钥进行签名。
即使已将数据库属性设置为 ON,Trustworthy
也会出现问题。
原因
出现此问题的原因是用于在服务器 A 上创建数据库的登录名不在服务器 B 上的 SQL Server 实例中。此登录名可以是Microsoft Windows 登录名或 SQL Server 登录名。
解决方法
若要解决此问题,请使用以下方法之一。
注意
在使用以下方法之前,请确保启用 Trustworthy
数据库属性。
sp_changedbowner
使用存储过程将数据库所有者更改为 sa 或服务器 B 上的可用登录名。例如,可以使用以下语句将数据库所有者更改为 sa:USE <DatabaseName> GO EXEC sp_changedbowner 'sa'
注意
在此语句中,
<DatabaseName>
是正在使用的数据库名称的占位符。 更改的数据库所有者应具有执行特定任务的相应权限。 例如,数据库所有者应具有创建程序集的 CREATE ASSEMBLY 权限。在服务器 A 上的 SQL Server 实例上添加登录名,该登录名用于将数据库创建到服务器 B 上的 SQL Server 实例。
如果登录名是域帐户,则可以在服务器 B 上创建相同的登录名。然后向服务器 B 上的 SQL Server 实例上的登录名授予所需的权限。
如果登录名是 SQL Server 登录名,请确保此登录名的 SID 与在服务器 B 上的 SQL Server 实例上创建的新 SQL Server 登录名匹配。为此,请指定语句的 CREATE LOGIN
SID 参数。
详细信息
如果从其他数据库访问 CLR 对象,并且该数据库具有不匹配的 DBO SID,则可能会出现相同的问题。
有关详细信息,请访问以下博客: CSS SQL Server 工程师。