[英]SQL Server 2008 Receive an user-defined table type in a CLR Stored Procedure?
[英]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
初始化结构?
我再次重新检查了文档,这次注意到两件事:
Parse
方法需要输入SqlString
(因为目的是从字符串转换),并且在 class 中定义的 UDT 必须具有不采用 arguments 的公共构造函数。 您可以选择创建额外的重载 class 构造函数。
我已经尝试了一些事情(使用您在问题中提供的代码),但到目前为止还无法让它按您的意愿工作。 我不确定即使使用重载的 class 构造函数,这是否会按您的意愿工作。 我相信执行重载构造函数的能力纯粹是为了您在 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
,但如果int_value.IsNull
为真,则Value
将是 null 引用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.