2011-12-11 16 views
8

tôi lưu giá trị long của tôi trong một bảng SQL Server như varbinary(max):SQL Server varbinary bigint với các giá trị khác nhau BitConverter.ToInt64

var savedValue = BitConverter.GetBytes(longValue); 

Bây giờ tôi cần phải làm việc với giá trị đó trong truy vấn T-SQL, nhưng khi Tôi đang cố gắng nhận giá trị:

select cast(Value as bigint) from dbo.MyValues 

Nó trả về giá trị số khác nhau. Ví dụ: nếu tôi đã lưu -8588797048854775808 trong .NET, trong T-SQL, tôi nhận được 33802181122903688

Hãy cho tôi biết vấn đề là gì? Có vấn đề nào giải quyết?

+3

tại sao bạn lưu số nguyên 64 bit dưới dạng biến thể ở vị trí đầu tiên? – BrokenGlass

+0

Thông thường bạn sẽ lưu trữ 'long' trong C# là' bigint' trong SQL Server. Có lý do cụ thể nào bạn đang cố lưu trữ 'long' như' varbinary' không? – rsbarro

+0

Vì trường DB đó không chỉ chứa giá trị kiểu int64. – Maybe

Trả lời

11

Truyền từ varbinary đến bigint (và ngược lại) sử dụng thứ tự byte mạng (lớn cuối). BitConverter sử dụng dấu chấm cuối của máy mà nó được chạy trên (nhỏ dành cho x86 và x64).

Do đó BitConverter.GetBytes chạy trên -8588797048854775808 (0x88CE7696E7167800) là {} 0x00,0x88,0xE9,0x18,0x69,0x89,0x31,0x77, và cast trên {0x00,0x88,0xE9,0x18,0x69,0x89,0x31, 0x77} là 0x0088E91869893177 = 38536887891734903.

Điều rõ ràng cần làm là chỉ lưu trữ số nguyên 64 bit làm số nguyên 64 bit ở vị trí đầu tiên.

Nếu bạn thực sự cần phải làm chuyển đổi này thì:

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

sẽ trao đổi xung quanh các byte, trong khi cũng bị cầm tay ở chỗ nó sẽ không trao đổi các byte nếu chạy trên một máy lớn về cuối nhỏ.

Ngoài ra, nếu bạn không muốn sử dụng namespace System.Net đối với một số lý do nào, hoặc nếu bạn muốn trở thành có thể mở rộng với các loại khác so với ba IPAddress.HostToNetworkOrder handeles, sử dụng:

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

Cảm ơn bạn đã giải thích về vấn đề này. Nhưng tôi không có ý định lưu các giá trị 'dài' thành 'varbinary' một lần nữa. Tôi chỉ cần một số công cụ để có được các giá trị 'bigint' hiện có trong cột đó như tôi nhận được các giá trị trong '.NET BitConverter.ToInt64'. Tôi cần một cái gì đó như 'Array.Reverse (savedValue);' chỉ trong môi trường truy vấn 'TSQL' – Maybe

+1

Thanx Jon Tôi đã tìm thấy! Trong trường hợp đó, tôi cần sử dụng hàm 'đảo ngược' trong' TSQL': 'chọn cast (cast (reverse (Value) như varbinary (max)) như bigint) từ dbo.MyValues' – Maybe

+0

Bất kể thiết kế DB của người hỏi , câu hỏi này đã giúp tôi giải quyết một vấn đề tương tự khi cố gắng thực hiện tương đương C# của hàm T-SQL HASHBYTES. Tôi thậm chí không nhận thức được khả năng của trật tự cuối cùng là khác nhau. Cảm ơn! –