Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何正确序列化可排序的SQLCLR用户定义类型?_C#_.net_Sql Server_Sorting_Sqlclr - Fatal编程技术网

C# 如何正确序列化可排序的SQLCLR用户定义类型?

C# 如何正确序列化可排序的SQLCLR用户定义类型?,c#,.net,sql-server,sorting,sqlclr,C#,.net,Sql Server,Sorting,Sqlclr,我正在C#中构建一个自定义的用户定义类型,用于SQL CLR 基础数据可以使用常规的有符号32位整数以4个字节表示。以下是实施方案: [可序列化] [SqlUserDefinedType(Format.UserDefined,IsByteOrdered=true, IsFixedLength=true,MaxByteSize=4)] 公共结构MyUDT:INullable,IBinarySerialize { 私有整数值; 公共整数值 { 获取{返回_值;} } 公共MyUDT(int值) :此

我正在C#中构建一个自定义的用户定义类型,用于SQL CLR

基础数据可以使用常规的有符号32位整数以4个字节表示。以下是实施方案:

[可序列化]
[SqlUserDefinedType(Format.UserDefined,IsByteOrdered=true,
IsFixedLength=true,MaxByteSize=4)]
公共结构MyUDT:INullable,IBinarySerialize
{
私有整数值;
公共整数值
{
获取{返回_值;}
}
公共MyUDT(int值)
:此()
{
_价值=价值;
}
公共重写字符串ToString()
{
返回_value.ToString(CultureInfo.InvariantCulture);
}
[SqlMethod(OnNullCall=false)]
公共静态MyUDT解析(SqlString)
{
int i=int.Parse(s.Value);
返回新的MyUDT(i);
}
公共bool为空{get;private set;}
公共静态MyUDT Null
{
获取{返回新的MyUDT{IsNull=true};}
}
公共无效读取(二进制读取器r)
{
var bytes=r.ReadBytes(4);
if(位转换器.IsLittleEndian)
Array.Reverse(字节);
int i=位转换器.ToInt32(字节,0);
_值=i^未选中((int)0x8000000);
}
公共无效写入(二进制写入程序w)
{
int i=_值^unchecked((int)0x8000000);
var bytes=BitConverter.GetBytes(i);
if(位转换器.IsLittleEndian)
Array.Reverse(字节);
w、 写入(字节);
}
}
当然,我将添加其他方法,使其更有用,但这是编译和发布的最低要求

我需要确保在将此类型用于比较时(例如,当它是表中的一列时),正确排序。将同时存在正值和负值

如您所见,我必须反转字节顺序,因为endianness是向后的。我还必须调整字节,使零表示为
0x8000000
,而-1则表示为
0x7FFFFFFF
。否则,这些值将无法正确排序

但是,SQL Server整数通常不是这样工作的。例如:

选择convert(varbinary,-16)--0xFFFFFFF0
选择convert(varbinary,16)--0x00000010
然而这些都很好!所以我只能得出结论,除了字节的原始顺序之外,还有其他排序类型。但在我的UDT中我找不到任何方法来控制它。可能吗

我发现的所有示例都显示了以下内容:

公共无效读取(二进制读取器r)
{
_value=r.ReadInt32();
}
公共无效写入(二进制写入程序w)
{
w、 写入(_值);
}
但这是一种完全不同的格式。它类似于SQL Server的格式,但结尾颠倒了(1是
0x01000000
,而-16是
0xF0FFFFFF
)。所以事情就完全错了。那么这些例子错了吗?某处有虫子吗

我还考虑过使用
Format.Native
并省略自定义序列化。这种方法是可行的,但我最终得到了5个字节的值,其中0看起来像
0x800000000
,而-1看起来像
0x7fffff00
。它像我一样自动转换,但它为
IsNull
布尔字段存储了一个额外的字节。它不接受将其标记为
[NonSerialized]
,也不允许我删除它。可空性是一项要求,因此必须存在

肯定有比进行位操作更简单的方法吗

另一个问题是,我的类型不能在SQL中直接转换为
int
。虽然,我不确定我是否需要它


另请参见DBA.SE上的a。

我怀疑您想要实现IComparable并将IsByteOrdered设置为false。这将通过将零转换为
0x8000000
和-1转换为
07FFFFFFF
消除玩游戏的需要


最后我要说的是,我甚至不是这方面的初学者。我自己从来没有这样做过,但我浏览了一下这里的文档:

那太好了,但是看看你链接的文档,在第一个“注意”框中,它说服务器不使用
IComparable
。它只是用于客户端的东西。我最感兴趣的是,在查询列中包含此UDT的表时,排序是否正确。啊,你是对的。对不起,那没用。您可以尝试使用Format.Native,这可能会迫使它序列化已签名的int,以便它们是可排序的(您自己就是这样做的)。至于存储NULL字节的它,如果您的类型确实不能为NULL,您可以尝试创建IsNull和NULL属性,以便它们不引用任何内容,并且只有不带集的get。