SQLCLR 程序集注册失败(类型加载失败)
SQLCLR assembly registration failed (Type load failed)
我正在尝试在 SqlServer 中注册 SQLCLR 程序集
CREATE ASSEMBLY [DatabaseCLR]
FROM 'T:\DatabaseCLR.dll'
WITH PERMISSION_SET = SAFE
GO
但在注册过程中我收到错误消息
Msg 6218, Level 16, State 2, Line 1 CREATE ASSEMBLY for assembly
'DatabaseCLR' failed because assembly 'DatabaseCLR' failed
verification. Check if the referenced assemblies are up-to-date and
trusted (for external_access or unsafe) to execute in the database.
CLR Verifier error messages if any will follow this message
[ :
DatabaseCLR.BinaryUtils::HasSetBits][mdToken=0x6000039] Type load
failed.
[token 0x02000008] Type load failed.
这与 this 问题中描述的相似。然而,情况有点不同。在我的程序集中,我不使用用户定义的类型。
如果我使用PERMISSION_SET = UNSAFE
程序集注册成功。不过,我似乎没有使用不安全的代码("Allow unsafe code" 项目属性中未选中复选框)(或者我这样做?)。
汇编代码(简体)为:
using System;
using System.Data.SqlTypes;
using System.Runtime.InteropServices;
using Microsoft.SqlServer.Server;
namespace DatabaseCLR
{
public class BinaryUtils
{
[SqlFunction(Name = "BinaryHasSetBits", IsDeterministic = true, IsPrecise = true)]
public static SqlBoolean HasSetBits(SqlBytes data)
{
if (data.IsNull)
return SqlBoolean.Null;
if (data.Storage != StorageState.Buffer)
throw new NotSupportedException(string.Format("Storage type {0} is not supported.", data.Storage));
long
len = data.Length,
ulen = len / sizeof(ulong),
tail = len % sizeof(ulong);
ByteToUlongConverter conv = new ByteToUlongConverter(data.Buffer);
for (long i = 0; i < ulen; i++)
if (conv.ulongs[i] != 0)
return SqlBoolean.True;
for (long i = len - tail; i < len; i++)
if (data.Buffer[i] != 0)
return SqlBoolean.True;
return SqlBoolean.False;
}
}
[StructLayout(LayoutKind.Explicit)]
internal struct ByteToUlongConverter
{
[FieldOffset(0)]
public byte[] bytes;
[FieldOffset(0)]
public ulong[] ulongs;
public ByteToUlongConverter(byte[] bytes)
{
this.ulongs = null;
this.bytes = bytes;
}
}
}
该程序集提供了对二进制类型进行按位运算的函数。我使用 struct
和 [StructLayout(LayoutKind.Explicit)]
属性将 byte[]
数组转换为 ulong[]
数组(以加快处理速度)。我猜 StructLayout
的使用会导致相关问题中的错误。但是它不在 UDT 上,我不知道在这种情况下如何修复它。
是否有机会使用 PERMISSION_SET = SAFE
注册程序集?
我将示例函数注册为
CREATE FUNCTION dbo.BinaryHasSetBits
(
@data varbinary(8000)
)
RETURNS BIT
AS EXTERNAL NAME [DatabaseCLR].[DatabaseCLR.BinaryUtils].[HasSetBits]
GO
我使用的是
的 x64 版本
- SqlServer 2014(为 .Net 4.0 编译的程序集)
- SqlServer 2008(为 .Net 2.0 编译的程序集)
错误是由于使用 LayoutKind.Explicit
。
改成LayoutKind.Sequential
[StructLayout(LayoutKind.Sequential)]
internal struct ByteToUlongConverter
{
...
}
使注册程序集成为可能PERMISSION_SET = SAFE
。
但是在这种情况下使用 LayoutKind.Sequential
而不是 LayoutKind.Explicit
会破坏语义。
因此,PERMISSION_SET = SAFE
或 LayoutKind.Explicit
,而不是两者。
我正在尝试在 SqlServer 中注册 SQLCLR 程序集
CREATE ASSEMBLY [DatabaseCLR]
FROM 'T:\DatabaseCLR.dll'
WITH PERMISSION_SET = SAFE
GO
但在注册过程中我收到错误消息
Msg 6218, Level 16, State 2, Line 1 CREATE ASSEMBLY for assembly 'DatabaseCLR' failed because assembly 'DatabaseCLR' failed verification. Check if the referenced assemblies are up-to-date and trusted (for external_access or unsafe) to execute in the database. CLR Verifier error messages if any will follow this message
[ : DatabaseCLR.BinaryUtils::HasSetBits][mdToken=0x6000039] Type load failed.
[token 0x02000008] Type load failed.
这与 this 问题中描述的相似。然而,情况有点不同。在我的程序集中,我不使用用户定义的类型。
如果我使用PERMISSION_SET = UNSAFE
程序集注册成功。不过,我似乎没有使用不安全的代码("Allow unsafe code" 项目属性中未选中复选框)(或者我这样做?)。
汇编代码(简体)为:
using System;
using System.Data.SqlTypes;
using System.Runtime.InteropServices;
using Microsoft.SqlServer.Server;
namespace DatabaseCLR
{
public class BinaryUtils
{
[SqlFunction(Name = "BinaryHasSetBits", IsDeterministic = true, IsPrecise = true)]
public static SqlBoolean HasSetBits(SqlBytes data)
{
if (data.IsNull)
return SqlBoolean.Null;
if (data.Storage != StorageState.Buffer)
throw new NotSupportedException(string.Format("Storage type {0} is not supported.", data.Storage));
long
len = data.Length,
ulen = len / sizeof(ulong),
tail = len % sizeof(ulong);
ByteToUlongConverter conv = new ByteToUlongConverter(data.Buffer);
for (long i = 0; i < ulen; i++)
if (conv.ulongs[i] != 0)
return SqlBoolean.True;
for (long i = len - tail; i < len; i++)
if (data.Buffer[i] != 0)
return SqlBoolean.True;
return SqlBoolean.False;
}
}
[StructLayout(LayoutKind.Explicit)]
internal struct ByteToUlongConverter
{
[FieldOffset(0)]
public byte[] bytes;
[FieldOffset(0)]
public ulong[] ulongs;
public ByteToUlongConverter(byte[] bytes)
{
this.ulongs = null;
this.bytes = bytes;
}
}
}
该程序集提供了对二进制类型进行按位运算的函数。我使用 struct
和 [StructLayout(LayoutKind.Explicit)]
属性将 byte[]
数组转换为 ulong[]
数组(以加快处理速度)。我猜 StructLayout
的使用会导致相关问题中的错误。但是它不在 UDT 上,我不知道在这种情况下如何修复它。
是否有机会使用 PERMISSION_SET = SAFE
注册程序集?
我将示例函数注册为
CREATE FUNCTION dbo.BinaryHasSetBits
(
@data varbinary(8000)
)
RETURNS BIT
AS EXTERNAL NAME [DatabaseCLR].[DatabaseCLR.BinaryUtils].[HasSetBits]
GO
我使用的是
的 x64 版本- SqlServer 2014(为 .Net 4.0 编译的程序集)
- SqlServer 2008(为 .Net 2.0 编译的程序集)
错误是由于使用 LayoutKind.Explicit
。
改成LayoutKind.Sequential
[StructLayout(LayoutKind.Sequential)]
internal struct ByteToUlongConverter
{
...
}
使注册程序集成为可能PERMISSION_SET = SAFE
。
但是在这种情况下使用 LayoutKind.Sequential
而不是 LayoutKind.Explicit
会破坏语义。
因此,PERMISSION_SET = SAFE
或 LayoutKind.Explicit
,而不是两者。