Converti da Oracle RAW (16) in .NET GUID

Sto riscontrando delle difficoltà nel debugging manuale di un’applicazione .NET in cui i valori di Guid differiscono da .NET a Oracle.

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

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

Se osservate i valori in questione (in coppia) di cifre esadecimali, potete vedere che gli ultimi 7 byte sono gli stessi in entrambi i casi, ma i primi 9 sono invertiti di un bit.

Partendo dal tuo esempio, ma riscrivendo ogni coppia in .NET come 00, 11, 22 ecc. E passando anche il byte rilevante di Oracle otteniamo:

  • .NETTO:

     00112233445566778899AABBCCDDEEFF 
  • Oracolo:

     33221100554477668899AABBCCFFEEFF 

Quindi dovrebbe essere abbastanza facile scrivere codice per passare intorno ai byte rilevanti. (Sono abbastanza sicuro di aver scritto del codice per farlo in un precedente lavoro, infatti.)

Per passare da un byte all’altro, devi chiamare Guid.ToByteArray() e il new Guid(byte[]) per tornare a un Guid .

EDIT: Come succede, il passaggio sopra è esattamente ciò che fa il costruttore Guid quando si passa a 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 

Ciò potrebbe rendere molto più semplice l’esecuzione della commutazione … come hai iniziato a ottenere i valori per iniziare? È solo “come vengono visualizzati in Oracle”?

EDIT: Ok, ecco un paio di funzioni di conversione – se hai i dati come testo, essi convertiranno 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; } } 

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

La risposta di Jon è corretta per l’interrogazione ma se la tua app ha bisogno di memorizzare e leggere Guid da Oracle, usa la funzione FlipEndian da questo thread:

Conversione GUID nativa .NET

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

Il flip è richiesto solo durante la lettura da Oracle.

Quando scrivi a Oracle usa Guid.ToByteArray () come al solito.

Ho passato troppo tempo a cercare di ottenere questo semplice compito.

Steve

Se hai bisogno di convertire un GUID in RAW da PL / SQL puoi usare 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; 

Usa sempre il tuo GUID standard in .NET …

Quando si desidera inserire un GUID in Oracle, basta chiamare Guid.ToString ( "N") e Guid.ToString ( "N") quella stringa a Oracle (in questo esempio il nome param è 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 leggi un RAW di Oracle, usi:

 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 è ansible alimentare il MyNETVal restituito nella new Guid (MyNETVal) .

In questo modo il tuo 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 ad altri DB – basta cambiare l’SQL e sei attivo e funzionante … l’SQL potrebbe diventare più semplice con altri DB perché alcuni di loro seguono il formato GUID di Windows …