将sql server rowversion转换为long或ulong?

时间:2014-01-15 19:02:07

标签: c# sql-server rowversion

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);

4 个答案:

答案 0 :(得分:17)

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

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

如果对签名的long执行相同的操作,0xFFFFFFFFFFFFFFFF代表-1。这意味着你的比较是不正确的;它不会与SQL Server中的相同比较匹配。

您真正想要的是使用 ulong 0xFFFFFFFFFFFFFFFFulong.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);
}