2011-09-02 34 views
27

Tengo dificultades para depurar manualmente una aplicación .NET donde los valores de Guid son diferentes de .NET a Oracle.Convertir de RAW (16) de Oracle a GUID de .NET

  • Donde C# lee:
    • 17D89D326C2142D69B989F5201288DBF
  • Oracle lee:
    • 329DD817216CD6429B989F5201288DBF

¿cómo iba a ser capaz de depurar manualmente, es decir, desde el GUID de C# ser capaz de pegar ese valor en una consulta de Oracle y obtener los resultados correctos (y viceversa)?

+0

duplicado posible de [Convertir matriz de bytes de Oracle RAW a System.Guid?] (Http://stackoverflow.com/questions/2667740/convert-byte-array-from-oracle-raw-to -system-guid) –

Respuesta

38

Si observa los valores implicados (en pares) de dígitos hexadecimales, puede ver que los últimos 7 bytes son los mismos en ambos casos, pero los primeros 9 se cambian un poco.

Yendo de su ejemplo, pero volver a escribir cada par en .NET como 00, 11, 22, etc y cambiar el byte correspondiente de Oracle, así obtenemos:

  • .NET:

    00112233445566778899AABBCCDDEEFF 
    
  • Oracle:

    33221100554477668899AABBCCFFEEFF 
    

Por lo tanto, debería ser bastante fácil escribir código para cambiar los bytes relevantes. (Estoy bastante seguro de que escribí algo de código para hacer esto en un trabajo anterior, de hecho.)

Para pasar alrededor de los bytes, sólo querrá llamar Guid.ToByteArray() y new Guid(byte[]) para volver a un Guid.

EDIT: Si llega el caso, el interruptor de todo el año anterior es exactamente lo que hace el Guid constructor cuando se le pasa una matriz de bytes:

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

Lienzo:

00112233445566778899AABBCCDDEEFF 
33221100554477668899aabbccddeeff 

Eso puede bueno, simplifica considerablemente el cambio ... ¿cómo conseguiste los valores para empezar? ¿Es solo "cómo se muestran en Oracle"?

EDIT: Bueno, aquí hay un par de funciones de conversión - si tiene los datos como texto, van a convertir en cada sentido ...

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

Resulta que no es Oracle quien está reordenando cosas. Es Guid.ToByteArray() y el constructor Guid que toma una matriz de bytes como su parámetro. No tengo idea de por qué hace esto, y he publicado una pregunta que pregunta exactamente eso aquí: http://stackoverflow.com/questions/9195551/why-does-guid-tobytearray-order-the-bytes-the-way -it-does –

1

sólo tiene que utilizar siempre la norma en GUID. RED...

Cuando desee insertar algún GUID en Oracle que acaba de llamar Guid.ToString ("N") y alimentar a esa cadena de Oracle (en este ejemplo el param name es 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; 

Cuando se leyó un RAW de Oracle que utilice :

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

a continuación, se puede alimentar a la volvieron MyNETVal en new Guid (MyNETVal).

De esta forma su código siempre trata con el formato .NET y la conmutación de bytes ocurre en el Oracle-DB ... usted no contamina su código con el código de conversión y puede mantener el mismo código al cambiar a otro DB - acaba de cambiar el SQL y que está en marcha y funcionando ... SQL podría conseguir más simple con otra DB debido a que algunos de ellos siguen el formato GUID de Windows ...

+0

eso no es lo que OP está pidiendo. Si supiera que .NET arruinaría las identificaciones, optaría por VARCHAR2 de inmediato. Pero ahora es demasiado tarde, ahora necesito encontrar la forma de unirlos – Toolkit

4

Si necesita convertir un GUID aRAW de PL/SQL puede utilizar esta función:

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

Acabo de tener este mismo problema al almacenar y leer Guids de Oracle.

respuesta de Jon es correcta para la consulta pero si su aplicación necesita para almacenar y leer GUID de Oracle, utilice la función FlipEndian de este hilo:

.NET Native GUID conversion

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

El flip sólo es necesario cuando la lectura de regreso de Oracle.

Al escribir en Oracle, utilice Guid.ToByteArray() de forma normal.

Pasé demasiado tiempo tratando de realizar esta sencilla tarea.

Steve

Cuestiones relacionadas