2011-12-11 13 views
8

guardo mi valor long en una tabla de SQL Server como varbinary(max):BitConverter.ToInt64 son diferentes

var savedValue = BitConverter.GetBytes(longValue); 

ahora tengo que trabajar con ese valor en la consulta de T-SQL, pero cuando Estoy tratando de obtener valor:

select cast(Value as bigint) from dbo.MyValues 

Devuelve un valor numérico diferente. Por ejemplo, si guardé -8588797048854775808 en .NET, en T-SQL obtengo 33802181122903688

¿Cuál es el problema? ¿Tiene ese problema alguna solución?

+3

¿por qué guardar un entero de 64 bits como varbinary en primer lugar? – BrokenGlass

+0

Normalmente, almacenaría 'long' en C# como' bigint' en SQL Server. ¿Hay alguna razón particular por la que intentas almacenar 'long' como' varbinary'? – rsbarro

+0

Porque ese campo DB no contiene solo valores de tipo int64. – Maybe

Respuesta

11

Casting de varbinary a bigint (y viceversa) utiliza el orden de bytes de la red (big-endian). BitConverter usa el endian-ness de la máquina en la que se ejecuta (little-endian para x86 y x64).

Por lo tanto BitConverter.GetBytes corrida en -8588797048854775808 (0x88CE7696E7167800) es {0x00,0x88,0xE9,0x18,0x69,0x89,0x31,0x77}, y cast en {0x00,0x88,0xE9,0x18,0x69,0x89,0x31, 0x77} es 0x0088E91869893177 = 38536887891734903.

Lo más obvio es almacenar números enteros de 64 bits como enteros de 64 bits en primer lugar.

Si realmente necesita hacer esta conversión a continuación:

var savedValue = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(longValue)) 

intercambiará alrededor de los bytes, además de ser portátil en el que no va a cambiar los bytes si se ejecuta en una máquina-big endian.

Como alternativa, si no desea utilizar el espacio de nombres System.Net por alguna razón, o si desea ser extensible a otros tipos de los tres IPAddress.HostToNetworkOrder handeles, utilice:

var savedValue = BitConverter.GetBytes(longValue); 
if(BitConverter.IsLittleEndian) 
    Array.Reverse(savedValue); 
+0

Gracias por su explicación de este problema. Pero no estoy planeando volver a guardar los valores 'largos' en 'varbinary'. Solo necesito alguna herramienta para obtener los valores 'bigint' existentes en esa columna, como obtener valores dentro de '.NET BitConverter.ToInt64'. Necesito algo como 'Array.Reverse (savedValue);' solo dentro del entorno de consulta 'TSQL' – Maybe

+1

Gracias Jon, encontré! En ese caso necesito usar la función 'reverse' en' TSQL': 'select cast (cast (reverse (Value) como varbinary (max)) como bigint) de dbo.MyValues' – Maybe

+0

Independientemente del diseño del DB del que realiza la petición , esta pregunta me ayudó a resolver un problema similar cuando intentaba implementar un equivalente de C# de una función HASHBYTES de T-SQL. Ni siquiera era consciente de la posibilidad de que el orden endian fuera diferente. ¡Gracias! –

Cuestiones relacionadas