43 votes

Conversion du RAW(16) d'Oracle en GUID de .NET

J'ai des difficultés à déboguer manuellement une application .NET dans laquelle les valeurs Guid diffèrent de .NET à Oracle.

  • Là où C# lit :
    • 17D89D326C2142D69B989F5201288DBF
  • Oracle lit :
    • 329DD817216CD6429B989F5201288DBF

Comment pourrais-je déboguer manuellement, c'est-à-dire, à partir du GUID de C#, être capable de coller cette valeur dans une requête oracle et obtenir les bons résultats (et vice versa) ?

0 votes

0 votes

Pourquoi je n'ai pas utilisé la ficelle ? fml

57voto

Jon Skeet Points 692016

Si vous regardez les valeurs impliquées (par paires) des chiffres hexadécimaux, vous pouvez voir que les 7 derniers octets sont les mêmes dans les deux cas, mais que les 9 premiers sont un peu intervertis.

En partant de votre exemple, mais en réécrivant chaque paire dans le .NET sous la forme 00, 11, 22, etc. et en changeant également l'octet correspondant d'Oracle, nous obtenons :

  • .NET :

    00112233445566778899AABBCCDDEEFF
  • Oracle :

    33221100554477668899AABBCCFFEEFF

Il devrait donc être assez facile d'écrire du code pour permuter les octets pertinents. (Je suis à peu près sûr d'avoir écrit du code pour faire cela dans un travail précédent, en fait).

Pour passer d'un octet à l'autre, il vous suffit d'appeler Guid.ToByteArray() y new Guid(byte[]) pour revenir à un Guid .

Il se trouve que l'interrupteur ci-dessus est exactement ce que le Guid fait quand vous lui passez un tableau d'octets :

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

Imprimés :

00112233445566778899AABBCCDDEEFF
33221100554477668899aabbccddeeff

Cela pourrait bien simplifier considérablement l'exécution de la commutation... Comment avez-vous obtenu les valeurs au départ ? Est-ce simplement "la façon dont elles sont affichées dans Oracle" ?

EDIT : Ok, voici quelques fonctions de conversion - si vous avez les données sous forme de texte, elles seront converties dans les deux sens...

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

}

14voto

samneric Points 452

Je viens de rencontrer le même problème lors du stockage et de la lecture de Guids à partir d'Oracle.

La réponse de Jon est correcte pour les requêtes mais si votre application doit stocker et lire des Guids depuis Oracle, utilisez la fonction FlipEndian de ce fil de discussion :

Conversion de GUID en natif .NET

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

Le retournement n'est nécessaire que lors de la relecture d'Oracle.

Pour écrire dans Oracle, utilisez Guid.ToByteArray() comme d'habitude.

J'ai passé TROP de temps à essayer d'accomplir cette simple tâche.

Steve

6voto

andreae75 Points 21

Si vous devez convertir un GUID a RAW de PL/SQL peut utiliser cette fonction :

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

1voto

Yahia Points 49011

Utilisez toujours votre standard GUID dans .NET...

Lorsque vous voulez insérer des GUID en Oracle, il suffit d'appeler Guid.ToString ( "N") et envoyez cette chaîne à Oracle (dans cet exemple le nom du paramètre est 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;

Lorsque vous lisez un RAW d'Oracle que vous utilisez :

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

Ensuite, vous pouvez nourrir le retour MyNETVal sur new Guid (MyNETVal) .

De cette façon, votre code traite toujours le format .NET et la commutation d'octets se produit dans la base de données Oracle... vous ne polluez pas votre code avec du code de conversion et vous pouvez garder le même code lorsque vous passez à d'autres bases de données - il suffit de changer le SQL et vous êtes opérationnel... le SQL pourrait être plus simple avec d'autres bases de données parce que certaines d'entre elles suivent le format GUID de Windows...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X