繁体   English   中英

SQL 服务器用户定义的 CLR 类型可以用除字符串以外的任何类型初始化吗?

[英]Can a SQL Server user defined CLR type be initialized by any type other than String?

我在 C# 中创建了一个 CLR 用户定义类型作为结构,我希望能够直接从 SQL 服务器中的int初始化此类型。 以下示例适用于字符串和 null 值,但适用于 int 失败,并显示消息:操作数类型冲突:int 与 ExhaustiveInt 不兼容

CREATE TABLE ExhaustiveTest (
    v ExhaustiveInt not null
);
insert into ExhaustiveTest 
values ('100'), (null), (100);

我在结构中尝试了以下内容:

using System;  
using System.Data;  
using System.Data.SqlTypes;  
using Microsoft.SqlServer.Server;

[Serializable]  
[Microsoft.SqlServer.Server.SqlUserDefinedType(
    Format.Native,  
    IsByteOrdered = true, 
    IsFixedLength = true,
    Name = "ExhaustiveInt",
    ValidationMethodName = "Validate"
)]  
public struct ExhaustiveInt : INullable {  
    private Int32   the_value;  
    private bool    is_unknown;
  
    public bool IsNull { 
        get {
            return false; 
        }
    }  

    public static ExhaustiveInt Null {  
        get {  
            ExhaustiveInt an_exhaustive_int = new ExhaustiveInt();  
            an_exhaustive_int.is_unknown = true;
            an_exhaustive_int.the_value = 0;
            return an_exhaustive_int;  
        }  
    }  

    public ExhaustiveInt(SqlInt32 int_value) {
        this.the_value = int_value.Value;
        this.is_unknown = int_value.IsNull;

    }
    public static explicit operator ExhaustiveInt(SqlInt32 int_value) {
        return new ExhaustiveInt(int_value);
    }
    
    public static ExhaustiveInt Parse(SqlString string_value) {
        ExhaustiveInt v = new ExhaustiveInt();  
        if(string_value.IsNull) {
            v.is_unknown = true;
            v.the_value = 0;
        }
        else {
            v.is_unknown = false;
            v.the_value = Int32.Parse(string_value.Value);
        }
        return v;
    }

    public override string ToString()  {  
        if (this.is_unknown)  
            return "Unknown";  
        else 
            return this.the_value.ToString(); 
    }  

    private bool Validate()  {  
        return true;  
    }  
  
    [SqlMethod(OnNullCall = false)]  
    public bool IsUnknown()  {  
        return this.is_unknown;  
    }  
}  

但是,似乎 SQL 服务器忽略了特定的构造函数和运算符。 有没有办法让 SQL 服务器明白有办法直接从int初始化结构?

我再次重新检查了文档,这次注意到两件事:

  1. Parse方法需要输入SqlString (因为目的是从字符串转换),并且
  2. 如果 UDT 是在 class 而非结构中定义的,则允许重载构造函数:

    在 class 中定义的 UDT 必须具有不采用 arguments 的公共构造函数。 您可以选择创建额外的重载 class 构造函数。

我已经尝试了一些事情(使用您在问题中提供的代码),但到目前为止还无法让它按您的意愿工作。 我不确定即使使用重载的 class 构造函数,这是否会按您的意愿工作。 我相信执行重载构造函数的能力纯粹是为了您在 CLR 代码中的内部使用,而不是从外部 T-SQL 上下文访问。 我相信 UDT 是在内部实例化的(也许解释了构造函数不带参数的要求),因此在我们与它们交互时已经存在,即使在DECLARE语句中也是如此。 意思是,我们可以这样称呼它:

  1.  DECLARE @Int dbo.ExhaustiveInt = NULL; DECLARE @Int dbo.ExhaustiveInt = 5;
    两者都调用Parse方法。
  2.  DECLARE @Int dbo.ExhaustiveInt = 0x1234567801; -- This is usually in the form of passing in another variable -- of the same UDT, or setting via: @Var = @Var.Method(val);
    这通过Read方法反序列化值(使用Format.Native时在内部处理,或使用Format.UserDefined时需要)。

在这两种情况下,类型已经存在以便调用ParseRead


另外,我认为它不会使用这个:

 public ExhaustiveInt(SqlInt32 int_value) {
        this.the_value = int_value.Value;
        this.is_unknown = int_value.IsNull;

    }

如果是这样,并且传入了NULL ,则会出错,因为您没有检查IsNull ,但如果int_value.IsNull为真,则Value将是 null 引用。

暂无
暂无

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

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