我正在尝试在SqlServer中注册SQLCLR程序集
CREATE ASSEMBLY [DatabaseCLR]
FROM 'T:DatabaseCLR.dll'
WITH PERMISSION_SET = SAFE
GO
但是在注册时我得到错误信息
Msg 6218, Level 16, State 2, Line 1'DatabaseCLR'失败,因为'DatabaseCLR'程序集失败验证。检查引用的程序集是否为最新的受信任(对于external_access或不安全)在数据库中执行。CLR验证程序错误消息(如果有的话)将跟随此消息
[:DatabaseCLR。BinaryUtils::HasSetBits][mdToken=0x6000039]类型加载失败了。
[token 0x02000008]类型加载失败。
,它与这个问题中描述的相似。然而,情况有点不同。在我的程序集中,我没有使用用户定义类型。
如果我使用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版本的
- 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
,而不是两者都有