2011-09-02 15 views
27

Mam problemy z ręcznym debugowaniem aplikacji .NET, gdzie wartości Guid różnią się od .NET do Oracle.Konwertuj z Oracle RAW (16) na GUID .NET

  • gdzie C# brzmi:
    • 17D89D326C2142D69B989F5201288DBF
  • Oracle brzmi:
    • 329DD817216CD6429B989F5201288DBF

Jak będę w stanie ręcznie debugować, tj. z GUID C# być w stanie wkleić tę wartość w kwerendzie Oracle i uzyskać poprawne wyniki (i viceversa)?

+0

Możliwy duplikat [Konwersja tablicy bajtów z Oracle RAW do System.Guid?] (Http://stackoverflow.com/questions/2667740/convert-byte-array-from-oracle-raw-to -system-guid) –

Odpowiedz

38

Jeśli spojrzysz na wartości związane (w parach) cyfr heksadecymalnych, zobaczysz, że 7 ostatnich bajtów w obu przypadkach jest takich samych, ale pierwsze 9 zostało nieco zmienione.

Idąc od Twojego przykład, ale przepisanie każdą parę w .NET jako 00, 11, 22 itp i przełączania odpowiedni bajt Oracle, a także otrzymujemy:

  • NET:

    00112233445566778899AABBCCDDEEFF 
    
  • Oracle:

    33221100554477668899AABBCCFFEEFF 
    

Powinno być dość łatwo napisać kod, aby przełączyć się na odpowiednie bajty. (Jestem pewien, że napisali trochę kodu do zrobienia tego w poprzedniej pracy, w rzeczywistości).

Aby przełączyć runda bajtów, to po prostu chcesz zadzwonić Guid.ToByteArray() i new Guid(byte[]) wrócić do Guid.

EDIT: Jak to się dzieje, przełącznik rundy powyżej dokładnie co robi konstruktor Guid kiedy przechodzą mu tablicę bajtów:

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("-", "")); 
    } 
} 

Drukuje:

00112233445566778899AABBCCDDEEFF 
33221100554477668899aabbccddeeff 

To może Cóż, znacznie ułatwiłoby to przełączanie ... jak zdobywałeś wartości, od których zaczynasz? Czy to po prostu "jak są wyświetlane w Oracle"?

EDIT: Dobra, oto kilka funkcji konwersji - jeśli masz dane jako tekst, oni przekształcić każdy sposób ...

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

Okazuje się, że to nie Oracle zmienia porządek rzeczy. To Guid.ToByteArray() i konstruktor Guid, który bierze tablicę bajtów jako jej parametr. Nie mam pojęcia, dlaczego to robi, a ja napisałem pytanie z pytaniem dokładnie tutaj: http://stackoverflow.com/questions/9195551/why-does-guid-tobytearray-order-the-bytes-the-way -to-does –

1

Wystarczy użyć zawsze standardowy GUID w. NETTO...

Gdy chcesz wstawić jakiś GUID do Oracle po prostu zadzwonić Guid.ToString ("N") i karmić ten ciąg do Oracle (w tym przykładzie param name jest 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; 

Kiedy czytasz RAW z Oracle użyć :

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); 

Następnie można karmić powrócił MyNETVal do new Guid (MyNETVal).

W ten sposób twój kod zawsze zajmuje się formatem .NET, a przełączanie bajtów odbywa się w Oracle-DB ... nie ignorujesz swojego kodu za pomocą kodu konwersji i możesz zachować kod taki sam, gdy przełączasz się na inne DB - po prostu zmień SQL i działaj poprawnie ... SQL może być prostszy w porównaniu z innymi bazami danych, ponieważ niektóre z nich są zgodne z formatem GUID systemu Windows ...

+0

nie o to pyta OP. Gdybym wiedziała, że ​​.NET zepsuje identyfikatory, od razu wybrałbym VARCHAR2. Ale teraz jest za późno, teraz muszę wymyślić, jak je dopasować – Toolkit

4

Jeśli chcesz przekonwertować GUID na RAW z PL/SQL mogą korzystać z tej funkcji:

/* 
    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

Po prostu miałem ten sam problem podczas przechowywania i czytania Guidów od Oracle.

odpowiedź Jon jest poprawna dla zapytań, ale jeśli Twoja aplikacja musi przechowywać i odczytywać GUID z Oracle, należy użyć funkcji FlipEndian z tego wątku:

.NET Native GUID conversion

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

klapka jest wymagane tylko podczas czytania wracamy z Oracle.

Pisząc do Oracle, używaj normalnie Guid.ToByteArray().

Spędziłem zbyt wiele czasu, próbując wykonać to proste zadanie.

Steve