如何解决SQL Server 用户定义的 CLR 类型可以由 String 以外的任何类型初始化吗?
我在 C# 中创建了一个 CLR 用户定义类型作为结构,我希望能够直接从 sql Server 中的 int
初始化这个类型。以下示例适用于字符串和空值,但对于 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 Server 似乎忽略了特定的构造函数和运算符。有没有办法让 sql Server 理解有一种方法可以直接从 int
初始化结构?
解决方法
我再次检查了 documentation,这次注意到两件事:
-
Parse
方法需要输入SqlString
(因为目的是从字符串转换),并且 - 如果 UDT 是在类中定义的,而不是在结构中定义,则允许重载构造函数:
在类中定义的 UDT 必须具有不带参数的公共构造函数。您可以选择创建额外的重载类构造函数。
我已经尝试了一些事情(使用您在问题中提供的代码),但到目前为止还没有按照您的意愿让它工作。我不确定即使使用重载的类构造函数,这也能像您想要的那样工作。我相信重载构造函数的能力纯粹是为了您在 CLR 代码中的内部使用,而不是从外部 T-SQL 上下文访问。我相信 UDT 是在内部实例化的(也许解释了构造函数不接受参数的要求),因此在我们与它们交互时已经存在,即使在 DECLARE
语句中也是如此。意思是,我们可以这样称呼它:
-
两者都调用DECLARE @Int dbo.ExhaustiveInt = NULL; DECLARE @Int dbo.ExhaustiveInt = 5;
Parse
方法。 -
这通过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
时需要)。
在这两种情况下,类型已经存在以便调用 Parse
或 Read
。
另外,我认为它不会使用这个:
public ExhaustiveInt(SqlInt32 int_value) {
this.the_value = int_value.Value;
this.is_unknown = int_value.IsNull;
}
如果是这样,并且传入了 NULL
,则会因为您没有检查 IsNull
而出错,但是如果 Value
是空引用,int_value.IsNull
将是真的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。