我在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
布尔字段存储了一个额外的字节。它不会接受标记为[NonSerialized]
的内容,也不会让我删除它。可空性是一项要求,因此它必须存在。
当然有一种比进行位操作更简单的方法吗?
另一个问题是我的类型不能直接转换为SQL中的int
。虽然,我不确定我是否需要。
另请参阅DBA.SE上的related (but different) question。
答案 0 :(得分:0)
我怀疑你想要实现IComparable并将IsByteOrdered设置为false。这样就无需通过将零转换为0x80000000
和-1转换为07FFFFFFF
来玩游戏。
我说完,我甚至不是这个东西的初学者。从来没有自己做过,但我在这里浏览了文档:http://msdn.microsoft.com/en-us/library/ms131082.aspx