Konvertieren von SQL Server Rowversion in Long oder Ulong?

Konvertieren von SQL Server Rowversion in Long oder Ulong?

Es spielt eine Rolle. Ihr Vergleich soll dasselbe Ergebnis haben wie der Vergleich von SQL Server. SQL Server verwendet vorzeichenlose Vergleiche für binäre Typen:

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

Wenn Sie dasselbe mit long machen die signiert ist, 0xFFFFFFFFFFFFFFFF steht für -1 . Das bedeutet, dass Ihr Vergleich falsch sein wird; es stimmt nicht mit dem gleichen Vergleich überein, der in SQL Server durchgeführt wird.

Was Sie auf jeden Fall wollen, ist die Verwendung von ulong wobei 0xFFFFFFFFFFFFFFFF ist ulong.MaxValue .

Endianness ist auch wichtig

Zusätzlich, wie Mark betonte, BitConverter.GetUInt64 konvertiert nicht richtig. Mark hat nicht ganz recht - BitConverter ist entweder Big-Endian oder Little-Endian, je nachdem, auf welchem ​​System es läuft. Sie können dies selbst sehen. Auch wenn BitConverter immer Little-Endian war, Array.Reverse ist mit einer Heap-Zuordnung und byteweisem Kopieren weniger leistungsfähig. BitConverter ist einfach weder semantisch noch praktisch das richtige Werkzeug für den Job.

Das wollen Sie:

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];
}

Die sauberste Lösung

Hier ist die Lösung, die ich verwende:Timestamp.cs.

Im Grunde sobald Sie auf Timestamp gecastet haben , Sie können nichts falsch machen.


Beides funktioniert aufgrund von Endian nicht richtig zum Vergleichen von Zeitstempel-/Zeilenversionswerten, wenn Sie auf einer CPU der x86-Familie ausgeführt werden. Das erste Byte eines Zeitstempels ist am signifikantesten, jedoch nicht für Little-Endian-Integer-Typen.

Rufen Sie Array.Reverse(ts) auf, bevor Sie BitConverter.ToUInt64(ts) aufrufen, und für die andere Richtung nach dem Aufruf von BitConverter.GetBytes(tsUInt64)


Kurze Antwort:Es spielt keine Rolle, aber ich würde UInt64 wählen .

Details:semantisch äquivalent zu binary(8) streng genommen ist es also weder UInt64 noch Int64 aber nur ein Stück Bytes (und auf diese Weise sollte es verwaltet werden). Das heißt, ich würde UInt64 wählen weil es eine aufsteigende Zahl ist Zeilenversion dann (aus logischer Sicht) 0xFFFFFFFFFFFFFFFF zu halten sollte größer als 0 sein und es ist nicht wahr für Int64 (weil 64 Bit auf 1 gesetzt -1 ergeben und es ist kleiner als 0 ).

Bearbeiten :Beachten Sie, dass aus Gründen, die nur im Kreis der SQL Server-Designer bekannt sind, ROWVERSION ist Big-Endian (während - offensichtlich - bigint ist nicht), dann müssen Sie zuerst Bytes umkehren, siehe diese Antwort für eine nette Implementierung.