gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 23:51:33 27 4
gpt4 key购买 nike

我正在用 C# 构建自定义用户定义类型以用于 SQL CLR。 See this reference .

底层数据可以使用常规带符号的 32 位整数以 4 个字节表示。这是实现:

[Serializable]
[SqlUserDefinedType(Format.UserDefined, IsByteOrdered = true,
IsFixedLength = true, MaxByteSize = 4)]
public struct MyUDT : INullable, IBinarySerialize
{
private int _value;

public int Value
{
get { return _value; }
}

public MyUDT(int value)
: this()
{
_value = value;
}

public override string ToString()
{
return _value.ToString(CultureInfo.InvariantCulture);
}

[SqlMethod(OnNullCall = false)]
public static MyUDT Parse(SqlString s)
{
int i = int.Parse(s.Value);
return new MyUDT(i);
}

public bool IsNull { get; private set; }
public static MyUDT Null
{
get { return new MyUDT { IsNull = true }; }
}

public void Read(BinaryReader r)
{
var bytes = r.ReadBytes(4);

if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);

int i = BitConverter.ToInt32(bytes, 0);
_value = i ^ unchecked((int) 0x80000000);
}

public void Write(BinaryWriter w)
{
int i = _value ^ unchecked((int) 0x80000000);
var bytes = BitConverter.GetBytes(i);

if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);

w.Write(bytes);
}
}

当然,我会添加其他方法使它更有用,但这是编译和发布的最低要求。

我需要确保当此类型用于比较时,例如当它是表中的列时,它被正确排序。既有正值也有负值。

如您所见,我不得不颠倒字节顺序,因为字节顺序是倒序的。我还必须调整字节,使零表示为 0x80000000,-1 变为 0x7FFFFFFF。否则值无法正确排序。

但是,这不是 SQL Server 整数的正常工作方式。例如:

SELECT convert(varbinary, -16)  -- 0xFFFFFFF0
SELECT convert(varbinary, 16) -- 0x00000010

然而这些排序就好了!所以我只能得出结论,除了原始字节顺序之外,还有其他排序类型。但是我找不到任何方法来在我的 UDT 中控制它。可能吗?

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

public void Read(BinaryReader r)
{
_value = r.ReadInt32();
}

public void Write(BinaryWriter w)
{
w.Write(_value);
}

但那是以一种完全不同的格式写的。它类似于 SQL Server 的格式,但字节序是相反的(1 是 0x01000000,-16 是 0xF0FFFFFF)。所以事情变得完全错误。那么这些例子是错误的吗?哪里有错误吗?

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

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

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

另见 related (but different) question在 DBA.SE 上。

最佳答案

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

最后我要说的是,我什至不是这方面的初学者。我自己从未做过,但我浏览了这里的文档:http://msdn.microsoft.com/en-us/library/ms131082.aspx

关于c# - 如何正确序列化可排序的 SQLCLR 用户定义类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17892082/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com