将sql server rowversion转换为long或ulong?

rowversion(timestamp)数据类型的正确类型是什么?

我知道这是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); 

简短的回答:没关系,但我会选择UInt64

细节:在语义上它等价于binary(8)所以,严格地说,它既不是UInt64也不是Int64而只是一块字节(并且以这种方式它应该被管理)。 那就是说我选择UInt64因为它是一个递增的数字来保存行版本然后(从逻辑的角度来看) 0xFFFFFFFFFFFFFFFF应该大于0并且对于Int64不是这样(因为64位设置为1给-1并且它更少比0 )。

编辑 :请注意,由于仅在内部SQL Server设计人员圈子中已知的原因, ROWVERSION是big-endian(而显然 – bigint不是),那么您首先需要反转字节,请参阅此答案以获得良好的实现 。

这非常重要。 您希望您的比较与SQL Server的比较具有相同的结果。 SQL Server对二进制类型使用无符号比较:

 select case when 0x0FFFFFFFFFFFFFFF < 0xFFFFFFFFFFFFFFFF then 'unsigned' else 'signed' end 

如果你对long签名做同样的事情, 0xFFFFFFFFFFFFFFFF代表-1 。 这意味着你的比较是不正确的; 它与SQL Server中完成的相同比较不匹配。

你绝对想要的是使用ulong ,其中0xFFFFFFFFFFFFFFFFulong.MaxValue

字节序也很重要

另外,正如Mark指出的那样, BitConverter.GetUInt64没有正确转换。 Mark 并不完全正确 - BitConverter要么是big-endian要么是little-endian,具体取决于它运行的系统。 你可以自己看看 。 此外,即使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 ,你就不会出错。

如果由于endian而在x86系列CPU上运行,则两者都不能正常用于比较时间戳/ rowversion值。 时间戳的第一个字节是最重要的,但对于小端整数类型则不是这样。

在调用BitConverter.ToUInt64(ts)之前调用Array.Reverse(ts),在调用BitConverter.GetBytes(tsUInt64)之后调用另一个方向

我用这个:

 private UInt64 GetUInt64ForRowVersion(byte[] rowVersion) { if (BitConverter.IsLittleEndian) { Array.Reverse(rowVersion); } return BitConverter.ToUInt64(rowVersion, 0); }