我试图在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'失败,因为汇编' DatabaseCLR'失败 验证。检查引用的程序集是否是最新的 信任(对于external_access或不安全)在数据库中执行。 CLR Verifier错误消息(如果有)将遵循此消息
[: DatabaseCLR.BinaryUtils :: HasSetBits] [mdToken = 0x6000039]输入load 失败。
[令牌0x02000008]类型加载失败。
与this问题中描述的类似。但情况有点不同。在我的程序集中,我不使用用户定义的类型。
如果我成功使用PERMISSION_SET = UNSAFE
汇编寄存器。我似乎并没有使用不安全的代码("允许不安全的代码"复选框未在项目属性中检查)(或者我?)。
汇编代码(简化)是:
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版本的
答案 0 :(得分:1)
该错误是由于使用了LayoutKind.Explicit
。
将其更改为LayoutKind.Sequential
[StructLayout(LayoutKind.Sequential)]
internal struct ByteToUlongConverter
{
...
}
可以使用PERMISSION_SET = SAFE
注册程序集。
但是在这种情况下,使用LayoutKind.Sequential
代替LayoutKind.Explicit
会破坏语义。
因此,PERMISSION_SET = SAFE
或LayoutKind.Explicit
不能同时使用。