SQL Server varbinary bigint со значениями BitConverter.ToInt64 отличаются - PullRequest
8 голосов
/ 12 декабря 2011

Я сохраняю свое значение long в таблице SQL Server как varbinary(max):

var savedValue = BitConverter.GetBytes(longValue);

Теперь мне нужно работать с этим значением в запросе T-SQL, но когда я пытаюсь получить значение:

select cast(Value as bigint) from dbo.MyValues

Возвращает другое числовое значение. Например, если я сохранил -8588797048854775808 в .NET, в T-SQL я получу 33802181122903688

Скажите, пожалуйста, в чем проблема? У этой проблемы есть какое-то решение?

1 Ответ

12 голосов
/ 12 декабря 2011

При приведении от varbinary к bigint (и обратно) используется сетевой порядок байтов (big-endian).BitConverter использует порядковый номер машины, на которой он запущен (little-endian для x86 и x64).

Следовательно, BitConverter.GetBytes run -8588797048854775808 (0x88CE7696E7167800) равен {0x00,0x88,0xE9,0x18,0x69,0x89,0x31,0x77} и cast для {0x00,0x88,0xE9,0x18,0x69,0x89,0x31,0x77} равно 0x0088E91869893177 = 38536887891734903.

Очевидно, что нужно сделать, этово-первых, просто хранить 64-битные целые числа как 64-битные.

Если вам действительно нужно выполнить это преобразование, то:

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

Поменяет местами байты, а такжебудучи переносимым в том смысле, что он не будет менять местами байты при запуске на машине с прямым порядком байтов.

В качестве альтернативы, если вы не хотите по какой-либо причине использовать пространство имен System.Net или если вы хотитебыть расширяемым для типов, отличных от трех IPAddress.HostToNetworkOrder handeles, используйте:

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