web-dev-qa-db-fra.com

Convertir d'Oracle RAW (16) en .NET GUID

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

  • Où C # indique:
    • 17D89D326C2142D69B989F5201288DBF
  • Oracle lit:
    • 329DD817216CD6429B989F5201288DBF

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

37
rebelliard

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

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

  • .NET:

    00112233445566778899AABBCCDDEEFF
    
  • Oracle:

    33221100554477668899AABBCCFFEEFF
    

Il devrait donc être assez facile d'écrire du code pour passer d'un octet à l'autre. (Je suis presque sûr d'avoir écrit du code pour le faire dans un travail précédent, en fait.)

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

EDIT: En l'occurrence, le basculement ci-dessus est exactement ce que fait le constructeur Guid lorsque 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("-", ""));
    }
}

Tirages:

00112233445566778899AABBCCDDEEFF
33221100554477668899aabbccddeeff

Cela pourrait bien simplifier considérablement la commutation ... comment avez-vous obtenu les valeurs pour commencer? Est-ce simplement "comment ils sont affichés dans Oracle"?

EDIT: D'accord, voici quelques fonctions de conversion - si vous avez les données sous forme de texte, elles seront converties dans chaque 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;
    }

}
50
Jon Skeet

Je viens d'avoir ce même problème lors du stockage et de la lecture des guides d'Oracle.

La réponse de Jon est correcte pour l'interrogation, mais si votre application doit stocker et lire des guides d'Oracle, utilisez la fonction FlipEndian de ce fil:

. NET Native GUID

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

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

Lorsque vous écrivez dans Oracle, utilisez Guid.ToByteArray () comme d'habitude.

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

Steve

9
samneric

Si vous devez convertir un GUID en BRUT 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;
5
andreae75

Utilisez toujours votre GUID standard dans .NET ...

Lorsque vous souhaitez insérer un GUID dans Oracle, vous appelez simplement Guid.ToString ( "N") et alimentez 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, 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 alimenter le MyNETVal retourné dans 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 le code de conversion et pouvez conserver le même code lors du passage à d'autres bases de données - changez simplement le SQL et vous êtes opérationnel ... le SQL pourrait devenir plus simple avec d'autres bases de données car certaines d'entre elles suivent le format GUID de Windows ...

1
Yahia