Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

convertire la versione di riga del server sql in long o ulong?

Conta. Si desidera che il confronto abbia lo stesso risultato del confronto di SQL Server. SQL Server utilizza confronti senza segno sui tipi binari:

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

Se fai la stessa cosa con long che è firmato, 0xFFFFFFFFFFFFFFFF rappresenta -1 . Ciò significa che il tuo confronto non sarà corretto; non corrisponderà allo stesso confronto eseguito in SQL Server.

Quello che vuoi assolutamente è usare ulong dove 0xFFFFFFFFFFFFFFFF è ulong.MaxValue .

Anche l'endianità è importante

Inoltre, come ha sottolineato Mark, BitConverter.GetUInt64 non si converte correttamente. Mark non ha completamente ragione - BitConverter è big-endian o little-endian a seconda del sistema su cui è in esecuzione. Puoi vedere di persona . Inoltre, anche se BitConverter è sempre stato little-endian, Array.Reverse è meno performante con un'allocazione heap e la copia byte per byte. BitConverter è semplicemente non semanticamente o praticamente lo strumento giusto per il lavoro.

Questo è quello che vuoi:

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

La soluzione più pulita

Aggiorna :se utilizzi .NET Core 2.1 o versioni successive (o .NET Standard 2.1), puoi utilizzare BinaryPrimitives.ReadUInt64BigEndian che si adatta perfettamente.

Su .NET Framework, ecco la soluzione che utilizzo:Timestamp.cs . Fondamentalmente dopo aver trasmesso a Timestamp , non puoi sbagliare.