2011-09-02 11 views
27

Ho difficoltà a eseguire il debug manuale di un'applicazione .NET in cui i valori di Guida differiscono da .NET a Oracle.Convertire da Oracle RAW (16) a .NET GUID

  • Dove C# si legge:
    • 17D89D326C2142D69B989F5201288DBF
  • Oracle si legge:
    • 329DD817216CD6429B989F5201288DBF

Come dovrei essere in grado di eseguire manualmente il debug, cioè, dal GUID di C# essere in grado di incollare quel valore in una query di Oracle e ottenere i risultati corretti (e viceversa)?

+0

Eventuali duplicati di [Convertire array di byte da Oracle RAW a System.Guid?] (Http://stackoverflow.com/questions/2667740/convert-byte-array-from-oracle-raw-to -system-guid) –

risposta

38

Se si osservano i valori in questione (in coppia) di cifre esadecimali, è possibile vedere che gli ultimi 7 byte sono uguali in entrambi i casi, ma i primi 9 vengono invertiti di un bit.

Andando dal vostro esempio, ma riscrivere ogni coppia in .NET come 00, 11, 22, ecc e il passaggio del relativo byte di Oracle così otteniamo:

  • .NET:

    00112233445566778899AABBCCDDEEFF 
    
  • Oracle:

    33221100554477668899AABBCCFFEEFF 
    

Quindi dovrebbe essere abbastanza facile scrivere codice per passare attorno ai byte rilevanti. (Io sono abbastanza sicuro che ho scritto il codice per fare questo in un lavoro precedente, in effetti.)

Per passare intorno ai byte, devi semplicemente desidera chiamare Guid.ToByteArray() e new Guid(byte[]) per tornare a un Guid.

EDIT: Come accade, l'interruttore-tutto sopra è esattamente quello costruttore Guid fa quando si passa un array di 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("-", "")); 
    } 
} 

stampe:

00112233445566778899AABBCCDDEEFF 
33221100554477668899aabbccddeeff 

Che può beh, rendere molto più semplice l'esecuzione della commutazione ... come ti stai avvicinando ai valori? È solo "come vengono visualizzati in Oracle"?

EDIT: Okay, qui ci sono un paio di funzioni di conversione - se hai i dati come testo, faranno convertire ogni modo ...

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

Si scopre che non è Oracle che sta riordinando le cose. È Guid.ToByteArray() e il costruttore Guid che accetta come parametro un array di byte. Non ho idea del motivo per cui lo fa, e ho postato una domanda chiedendo esattamente che qui: http://stackoverflow.com/questions/9195551/why-does-guid-tobytearray-order-the-bytes-the-way -It-fa –

1

Basta utilizzare sempre il vostro standard GUID in. NETTO...

Quando si vuole inserire qualche GUID in Oracle basta chiamare Guid.ToString ("N") e mangimi che stringa da Oracle (in questo esempio il param name è 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; 

Quando si legge un RAW da Oracle si utilizza :

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

Quindi è possibile alimentare il restituito MyNETVal in new Guid (MyNETVal).

In questo modo il codice si occupa sempre del formato .NET e il cambio di byte avviene nel DB Oracle ... non si polarizza il codice con il codice di conversione e si può mantenere lo stesso codice di codice quando si passa a altro DB: basta modificare l'SQL e si è attivi e in esecuzione ... l'SQL potrebbe diventare più semplice con altri DB perché alcuni seguono il formato GUID di Windows ...

+0

non è quello che l'OP sta chiedendo. Se avessi saputo che .NET avrebbe rovinato gli ID, avrei optato subito per VARCHAR2. Ma ora è troppo tardi, ora ho bisogno di capire come abbinarli – Toolkit

4

Se è necessario convertire un GUID GUIDRAW da PL/SQL possibile utilizzare questa funzione:

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

Ho appena avuto lo stesso problema durante l'archiviazione e la lettura di Guids da Oracle.

risposta di Jon è corretta per l'interrogazione, ma se la vostra applicazione ha bisogno di memorizzare e leggere GUID da Oracle, utilizzare la funzione FlipEndian da questa discussione:

.NET Native GUID conversion

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

Il flip è richiesto solo quando la lettura ritorno da Oracle.

Quando si scrive su Oracle, utilizzare Guid.ToByteArray() come di consueto.

Ho trascorso troppo tempo cercando di ottenere questo semplice compito.

Steve