What is the proper type for the rowversion (timestamp) data type?
I know it is 8 bytes but i cannot find a link in MSDN which tell if it is a signed or unsigned long.
which code should I use, does it even matter?
byte[] SqlTimeStamp;
long longConversion;
longConversion = BitConverter.ToInt64(SqlTimeStamp,0);
TimeStamp = BitConverter.GetBytes(longConversion);
ulong ulongConversion;
ulongConversion = BitConverter.ToUInt64(SqlTimeStamp,0);
TimeStamp = BitConverter.GetBytes(ulongConversion);
I use this:
Neither will work correctly for purposes of comparing timestamp/rowversion values, if you're running on an x86 family CPU, because of endian. The first byte of a timestamp is most significant, but not so for little endian integer types.
Call Array.Reverse(ts) before calling BitConverter.ToUInt64(ts), and for the other direction, after calling BitConverter.GetBytes(tsUInt64)
Short answer: it doesn't matter but I'd choose
UInt64
.Details: semantically it's equivalent to
binary(8)
so, strictly speaking, it's neitherUInt64
norInt64
but just a chunk of bytes (and in that way it should be managed). That said I'd chooseUInt64
because it's an incrementing number to hold row version then (from a logic point of view)0xFFFFFFFFFFFFFFFF
should be greater than0
and it's not true forInt64
(because 64 bits set to 1 give-1
and it's less than0
).Edit: note that, for reasons known only in the innest SQL Server designers circle,
ROWVERSION
is big-endian (while - obviously -bigint
is not) then you first need to reverse bytes, see this answer for a nice implementation.It does matter. You want your comparison to have the same result as SQL Server's comparison. SQL Server uses unsigned comparisons on binary types:
If you do the same thing with
long
which is signed,0xFFFFFFFFFFFFFFFF
represents-1
. That means your comparison will be incorrect; it won't match with the same comparison done in SQL Server.What you definitely want is to use
ulong
where0xFFFFFFFFFFFFFFFF
isulong.MaxValue
.Endianness is also important
Additionally, as Mark pointed out,
BitConverter.GetUInt64
is not converting properly. Mark is not completely right-BitConverter
is either big-endian or little-endian depending on the system it's running on. You can see this for yourself. Also, even if BitConverter was always little-endian,Array.Reverse
is less performant with a heap allocation and byte-by-byte copying.BitConverter
is just not semantically or practically the right tool for the job.This is what you want:
The cleanest solution
Here is the solution I use: Timestamp.cs.
Basically once you cast to
Timestamp
, you can't go wrong.