rowversion(时间戳)数据类型的正确类型是什么?
我知道它是8个字节但是我找不到MSDN中的链接,它告诉它是签名还是无符号长。
我应该使用哪些代码,这甚至是否重要?
byte[] SqlTimeStamp;
long longConversion;
longConversion = BitConverter.ToInt64(SqlTimeStamp,0);
TimeStamp = BitConverter.GetBytes(longConversion);
ulong ulongConversion;
ulongConversion = BitConverter.ToUInt64(SqlTimeStamp,0);
TimeStamp = BitConverter.GetBytes(ulongConversion);
答案 0 :(得分:17)
这很重要。您希望您的比较与SQL Server的比较具有相同的结果。 SQL Server对二进制类型使用无符号比较:
select case when 0x0FFFFFFFFFFFFFFF < 0xFFFFFFFFFFFFFFFF then 'unsigned' else 'signed' end
如果对签名的long
执行相同的操作,0xFFFFFFFFFFFFFFFF
代表-1
。这意味着你的比较是不正确的;它不会与SQL Server中的相同比较匹配。
您真正想要的是使用 ulong
,0xFFFFFFFFFFFFFFFF
为ulong.MaxValue
。
此外,正如马克指出的那样,BitConverter.GetUInt64
没有正确转换。 Mark 不完全正确 - BitConverter
是big-endian或little-endian,具体取决于它运行的系统。你可以see this for yourself。此外,即使BitConverter始终是little-endian,Array.Reverse
在堆分配和逐字节复制方面的性能也较差。 BitConverter
在语义上或实际上都不是正确的工具。
这就是你想要的:
static ulong BigEndianToUInt64(byte[] bigEndianBinary)
{
return ((ulong)bigEndianBinary[0] << 56) |
((ulong)bigEndianBinary[1] << 48) |
((ulong)bigEndianBinary[2] << 40) |
((ulong)bigEndianBinary[3] << 32) |
((ulong)bigEndianBinary[4] << 24) |
((ulong)bigEndianBinary[5] << 16) |
((ulong)bigEndianBinary[6] << 8) |
bigEndianBinary[7];
}
以下是我使用的解决方案:Timestamp.cs。
基本上,一旦你投向Timestamp
,你就不会出错。
答案 1 :(得分:9)
如果你在x86系列CPU上运行,因为有了endian,它们都不能正常用于比较时间戳/ rowversion值。时间戳的第一个字节是最重要的,但对于小端整数类型则不是这样。
在调用BitConverter.ToUInt64(ts)之前调用Array.Reverse(ts),在调用BitConverter.GetBytes(tsUInt64)之后调用另一个方向
答案 2 :(得分:6)
简短回答:没关系,但我选择UInt64
。
细节:在语义上它等同于binary(8)
所以,严格地说,它既不是UInt64
也不是Int64
,而只是一块字节(并且以这种方式应该被管理)。这就是说我选择UInt64
,因为它是递增数来保存行版本然后(从逻辑角度来看)0xFFFFFFFFFFFFFFFF
应该大于0
并且Int64
不是这样(因为设置为1的64位给-1
并且它小于0
。)
编辑:请注意,由于仅在内嵌SQL Server设计人员圈子中已知的原因,ROWVERSION
是big-endian(而 - 显然 - bigint
不是)然后首先需要反转字节,请参阅this answer for a nice implementation。
答案 3 :(得分:1)
我用这个:
private UInt64 GetUInt64ForRowVersion(byte[] rowVersion)
{
if (BitConverter.IsLittleEndian) { Array.Reverse(rowVersion); }
return BitConverter.ToUInt64(rowVersion, 0);
}