Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

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 ulong zu verwenden 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 sich selbst davon überzeugen . 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

Aktualisieren :Wenn Sie .NET Core 2.1 oder höher (oder .NET Standard 2.1) verwenden, können Sie BinaryPrimitives.ReadUInt64BigEndian das passt perfekt.

Auf .NET Framework ist hier die Lösung, die ich verwende:Timestamp.cs . Im Grunde sobald Sie zu Timestamp gecastet haben , Sie können nichts falsch machen.