sql >> Base de Datos >  >> RDS >> Sqlserver

¿convirtiendo la versión de fila del servidor sql en long o ulong?

Sí importa. Desea que su comparación tenga el mismo resultado que la comparación de SQL Server. SQL Server usa comparaciones sin firmar en tipos binarios:

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

Si haces lo mismo con long que está firmado, 0xFFFFFFFFFFFFFFFF representa -1 . Eso significa que su comparación será incorrecta; no coincidirá con la misma comparación realizada en SQL Server.

Lo que definitivamente quieres es usar ulong donde 0xFFFFFFFFFFFFFFFF es ulong.MaxValue .

El endianismo también es importante

Además, como señaló Mark, BitConverter.GetUInt64 no está convirtiendo correctamente. Mark no tiene toda la razón - BitConverter es big-endian o little-endian según el sistema en el que se esté ejecutando. Puede ver esto por sí mismo . Además, incluso si BitConverter siempre fue little-endian, Array.Reverse tiene menos rendimiento con una asignación de almacenamiento dinámico y una copia byte a byte. BitConverter simplemente no es semántica o prácticamente la herramienta adecuada para el trabajo.

Esto es lo que quieres:

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 solución más limpia

Actualizar :si usa .NET Core 2.1 o posterior (o .NET Standard 2.1), puede usar BinaryPrimitives.ReadUInt64BigEndian que es un ajuste perfecto.

En .NET Framework, esta es la solución que uso:Timestamp.cs . Básicamente, una vez que envías a Timestamp , no te puedes equivocar.