简体   繁体   English

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

[英]SQLCLR assembly registration failed (Type load failed)

I'm trying to register SQLCLR assembly in SqlServer我正在尝试在 SqlServer 中注册 SQLCLR 程序集

CREATE ASSEMBLY [DatabaseCLR]
FROM 'T:\DatabaseCLR.dll'
WITH PERMISSION_SET = SAFE
GO

but during registration I get error message但在注册期间我收到错误消息

Msg 6218, Level 16, State 2, Line 1 CREATE ASSEMBLY for assembly 'DatabaseCLR' failed because assembly 'DatabaseCLR' failed verification.消息 6218,级别 16,状态 2,第 1 行为程序集“DatabaseCLR”创建程序集失败,因为程序集“DatabaseCLR”验证失败。 Check if the referenced assemblies are up-to-date and trusted (for external_access or unsafe) to execute in the database.检查引用的程序集是否是最新的并且受信任(对于 external_access 或不安全)以在数据库中执行。 CLR Verifier error messages if any will follow this message CLR 验证器错误消息(如果有)将跟随此消息
[ : DatabaseCLR.BinaryUtils::HasSetBits][mdToken=0x6000039] Type load failed. [ : DatabaseCLR.BinaryUtils::HasSetBits][mdToken=0x6000039] 类型加载失败。
[token 0x02000008] Type load failed. [令牌 0x02000008] 类型加载失败。

which is similar to one described in this question.这类似于这个问题中描述的一个。 However the situation is a bit different.然而,情况有点不同。 In my assembly I do not use User-Defined Types.在我的程序集中,我不使用用户定义的类型。

If I use PERMISSION_SET = UNSAFE the assembly registers successfully.如果我使用PERMISSION_SET = UNSAFE程序集注册成功。 It doesn't seem that I use unsafe code though ("Allow unsafe code" checkbox is not checked in project properties) (or do I?).虽然我似乎没有使用不安全代码(项目属性中未选中“允许不安全代码”复选框)(或者我这样做?)。

The assembly code (simplified) is:汇编代码(简化)是:

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;
        }
    }
}

The assembly provides functions for bitwise operations on binary types.该程序集提供了对二进制类型进行按位运算的函数。 I'm using struct with [StructLayout(LayoutKind.Explicit)] attribute for casting byte[] array to ulong[] array (to speed up processing).我正在使用带有[StructLayout(LayoutKind.Explicit)]属性的struct来将byte[]数组转换为ulong[]数组(以加快处理速度)。 I guess that use of StructLayout causes error as in the related question.我猜StructLayout使用会导致相关问题中的错误。 However it is not on UDT, and I do not see how I can fix it in this case.但是它不在 UDT 上,我不知道在这种情况下如何修复它。

Are there any chances to register assembly with PERMISSION_SET = SAFE ?是否有机会使用PERMISSION_SET = SAFE注册程序集?


I do register my sample function as我确实将我的示例函数注册为

CREATE FUNCTION dbo.BinaryHasSetBits
(
    @data varbinary(8000)
)
RETURNS BIT
AS EXTERNAL NAME [DatabaseCLR].[DatabaseCLR.BinaryUtils].[HasSetBits]
GO

I'm using x64 editions of我正在使用 x64 版本的

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

The error is due to use of LayoutKind.Explicit .该错误是由于使用了LayoutKind.Explicit

Changing it to LayoutKind.Sequential将其更改为LayoutKind.Sequential

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

makes possible registering assembly with PERMISSION_SET = SAFE .可以使用PERMISSION_SET = SAFE注册程序集。

But using LayoutKind.Sequential instead of LayoutKind.Explicit breaks semantics in this case.但是在这种情况下使用LayoutKind.Sequential而不是LayoutKind.Explicit会破坏语义。

So, PERMISSION_SET = SAFE or LayoutKind.Explicit , not both.因此, PERMISSION_SET = SAFELayoutKind.Explicit ,而不是两者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM