SQLCLR程序集注册失败(类型加载失败)



我正在尝试在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 = SAFELayoutKind.Explicit,而不是两者都有

最新更新