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

时间:2016-11-11 08:11:55

标签: c# .net sql-server sqlclr

我试图在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版本的

  • SqlServer 2014(为.Net 4.0编译的程序集)
  • SqlServer 2008(为.Net 2.0编译的程序集)

1 个答案:

答案 0 :(得分:1)

该错误是由于使用了LayoutKind.Explicit

将其更改为LayoutKind.Sequential

[StructLayout(LayoutKind.Sequential)]
internal struct ByteToUlongConverter
{
    ...
}

可以使用PERMISSION_SET = SAFE注册程序集。

但是在这种情况下,使用LayoutKind.Sequential代替LayoutKind.Explicit会破坏语义。

因此,PERMISSION_SET = SAFELayoutKind.Explicit不能同时使用。