2011-09-02 21 views
27

Tôi đang gặp khó khăn khi gỡ lỗi thủ công ứng dụng .NET nơi các giá trị Guid khác với .NET với Oracle.Chuyển đổi từ RAW của RAW (16) sang .NET của GUID

  • đâu C# đọc:
    • 17D89D326C2142D69B989F5201288DBF
  • Oracle lần đọc:
    • 329DD817216CD6429B989F5201288DBF

Làm thế nào tôi sẽ có thể gỡ lỗi thủ công, tức là, từ GUID của C# có thể dán giá trị đó vào một truy vấn oracle và nhận được kết quả chính xác (và viceversa)?

+0

trùng lặp có thể xảy ra của [Chuyển đổi mảng byte từ Oracle RAW để System.Guid?] (Http://stackoverflow.com/questions/2667740/convert-byte-array-from-oracle-raw-to -system-guid) –

Trả lời

38

Nếu bạn xem các giá trị liên quan (theo cặp) của các chữ số thập phân, bạn có thể thấy 7 byte cuối cùng giống nhau trong cả hai trường hợp, nhưng 9 byte đầu tiên được chuyển xung quanh một chút.

Đi từ ví dụ của bạn, nhưng viết lại mỗi cặp trong .NET như 00, 11, 22 vv và chuyển đổi các byte liên quan của Oracle cũng chúng tôi nhận được:

  • NET:

    00112233445566778899AABBCCDDEEFF 
    
  • Oracle:

    33221100554477668899AABBCCFFEEFF 
    

Vì vậy, nó khá dễ dàng để viết mã để chuyển đổi vòng các byte có liên quan. (Tôi khá chắc chắn rằng tôi đã viết một số mã để thực hiện việc này trong công việc trước đây, trên thực tế.)

Để chuyển đổi các byte, bạn chỉ cần gọi Guid.ToByteArray()new Guid(byte[]) để quay lại Guid.

EDIT: Vì nó xảy ra, công tắc quanh trên là chính xác những gì các nhà xây dựng Guid làm khi bạn vượt qua nó một mảng byte:

using System; 
using System.Linq; 

class Test 
{ 
    static void Main() 
    { 
     byte[] bytes = Enumerable.Range(0, 16) 
           .Select(x => x * 16 + x) 
           .Select(x => (byte) x) 
           .ToArray(); 

     Console.WriteLine(BitConverter.ToString(bytes).Replace("-", "")); 
     Console.WriteLine(new Guid(bytes).ToString().Replace("-", "")); 
    } 
} 

Prints:

00112233445566778899AABBCCDDEEFF 
33221100554477668899aabbccddeeff 

Đó có thể cũng làm cho nó đơn giản hơn đáng kể để thực hiện chuyển đổi ... làm thế nào bạn có được giữ các giá trị để bắt đầu? Nó chỉ là "cách chúng được hiển thị trong Oracle"?

EDIT: OK, đây là một vài chức năng chuyển đổi - nếu bạn đã có dữ liệu dưới dạng văn bản, họ sẽ chuyển đổi mỗi chiều ...

using System; 
using System.Linq; 

class Test 
{ 
    static void Main() 
    { 
     string oracle = "329DD817216CD6429B989F5201288DBF"; 
     string dotNet = "17D89D326C2142D69B989F5201288DBF"; 

     Console.WriteLine(oracle == DotNetToOracle(dotNet)); 
     Console.WriteLine(dotNet == OracleToDotNet(oracle)); 
    } 

    static string OracleToDotNet(string text) 
    { 
     byte[] bytes = ParseHex(text); 
     Guid guid = new Guid(bytes); 
     return guid.ToString("N").ToUpperInvariant(); 
    } 

    static string DotNetToOracle(string text) 
    { 
     Guid guid = new Guid(text); 
     return BitConverter.ToString(guid.ToByteArray()).Replace("-", ""); 
    } 

    static byte[] ParseHex(string text) 
    { 
     // Not the most efficient code in the world, but 
     // it works... 
     byte[] ret = new byte[text.Length/2]; 
     for (int i = 0; i < ret.Length; i++) 
     { 
      ret[i] = Convert.ToByte(text.Substring(i * 2, 2), 16); 
     } 
     return ret; 
    } 

} 
+0

Nó chỉ ra rằng nó không phải là Oracle đó là sắp xếp lại mọi thứ. Đó là Guid.ToByteArray() và hàm tạo Guid lấy một mảng byte làm tham số của nó. Tôi không có ý tưởng tại sao nó làm điều này, và tôi đã đăng một câu hỏi yêu cầu chính xác rằng ở đây: http://stackoverflow.com/questions/9195551/why-does-guid-tobytearray-order-the-bytes-the-way -it-does –

1

Chỉ cần sử dụng luôn chuẩn GUID trong. MẠNG LƯỚI...

Khi bạn muốn chèn một số GUID vào Oracle bạn chỉ cần gọi Guid.ToString ("N") và thức ăn chuỗi đó để Oracle (trong ví dụ này tên param là MyNETVAL):

INSERT INTO MyTable (MyRAWCol) 
SELECT HEXTORAW (SUBSTR (MyNETVal, 6, 2) || SUBSTR (MyNETVal, 4, 2) || SUBSTR (MyNETVal, 2, 2) || SUBSTR (MyNETVal, 0, 2) || SUBSTR (MyNETVal, 10, 2) || SUBSTR (MyNETVal, 8, 2) || SUBSTR (MyNETVal, 14, 2) || SUBSTR (MyNETVal, 12, 2) || SUBSTR (MyNETVal, 16, 16)) FROM DUAL; 

Khi bạn đọc một RAW từ Oracle bạn sử dụng :

SELECT 
SUBSTR (HexV, 6, 2) || SUBSTR (HexV, 4, 2) || SUBSTR (HexV, 2, 2) || SUBSTR (HexV, 0, 2) || SUBSTR (HexV, 10, 2) || SUBSTR (HexV, 8, 2) || SUBSTR (HexV, 14, 2) || SUBSTR (HexV, 12, 2) || SUBSTR (HexV, 16, 16) AS MyNETVal 
FROM (SELECT RAWTOHEX (MyRAWCol) HexV FROM MyTable); 

Sau đó, bạn có thể ăn trở MyNETVal vào new Guid (MyNETVal). Bằng cách này mã của bạn luôn luôn giao dịch với định dạng .NET và chuyển đổi byte xảy ra trong Oracle-DB ... bạn không polute mã của bạn với mã chuyển đổi và có thể giữ mã code giống nhau khi chuyển sang khác DBs - chỉ cần thay đổi SQL và bạn đang lên và chạy ... SQL có thể trở nên đơn giản hơn với các DB khác vì một số người trong số họ tuân theo định dạng GUID của Windows ...

+0

đó không phải là những gì OP đang yêu cầu. Nếu tôi biết. NET sẽ vít lên ID tôi sẽ lựa chọn không cho VARCHAR2 ngay lập tức. Nhưng bây giờ đã quá muộn, bây giờ tôi cần tìm cách kết hợp chúng – Toolkit

4

Nếu bạn cần chuyển đổi GUID thành RAW từ PL/SQL có thể sử dụng chức năng này:

/* 
    CONVERT a GUID FORMAT in RAW(16) 
    EX: 
     guid = 88c6a267-65d2-48d6-8da2-6f45e2c22726 
     raw  = 67A2C688D265D6488DA26F45E2C22726 
*/ 
FUNCTION GuidToRaw(guid IN VARCHAR2) RETURN RAW 
IS 
    ret   RAW(16); 
    guidHex  VARCHAR2(64); 
BEGIN 

    guidHex := SUBSTR (guid, 7, 2); 
    guidHex := CONCAT(guidHex, SUBSTR (guid, 5, 2)); 
    guidHex := CONCAT(guidHex, SUBSTR (guid, 3, 2)); 
    guidHex := CONCAT(guidHex, SUBSTR (guid, 1, 2)); 

    guidHex := CONCAT(guidHex, SUBSTR (guid, 12, 2)); 
    guidHex := CONCAT(guidHex, SUBSTR (guid, 10, 2)); 

    guidHex := CONCAT(guidHex, SUBSTR (guid, 17, 2)); 
    guidHex := CONCAT(guidHex, SUBSTR (guid, 15, 2)); 

    guidHex := CONCAT(guidHex, SUBSTR (guid, 20, 2)); 
    guidHex := CONCAT(guidHex, SUBSTR (guid, 22, 2)); 

    guidHex := CONCAT(guidHex, SUBSTR (guid, 25, 12)); 

    ret := HEXTORAW(guidHex); 

    return ret; 

end; 
3

Tôi vừa gặp vấn đề tương tự khi lưu trữ và đọc hướng dẫn từ Oracle.

câu trả lời của Jon là đúng cho các truy vấn nhưng nếu ứng dụng của bạn cần phải lưu trữ và đọc Guids từ Oracle, sử dụng chức năng FlipEndian từ chủ đề này:

.NET Native GUID conversion

Byte[] rawBytesFromOracle; 
Guid dotNetGuid = new Guid(rawBytesFromOracle).FlipEndian(); 

Các lật chỉ được yêu cầu khi đọc từ Oracle.

Khi viết thư cho Oracle, hãy sử dụng Guid.ToByteArray() như bình thường.

Tôi đã dành quá nhiều thời gian để cố gắng hoàn thành nhiệm vụ đơn giản này.

Steve

Các vấn đề liên quan