Конвертировать из Oracle RAW (16) в GUID .NET - PullRequest
35 голосов
/ 03 сентября 2011

У меня возникают трудности при ручной отладке приложения .NET, где значения Guid отличаются от .NET к Oracle.

  • Где C # гласит:
    • 17D89D326C2142D69B989F5201288DBF
  • Oracle читает:
    • 329DD817216CD6429B989F5201288DBF

Как я смогу отладить вручную, то есть, используя GUID C #, вставить это значение в запрос оракула и получить правильные результаты (и наоборот)?

Ответы [ 4 ]

48 голосов
/ 03 сентября 2011

Если вы посмотрите на значения (в парах) шестнадцатеричных цифр, вы увидите, что последние 7 байтов одинаковы в обоих случаях, но первые 9 переключаются немного.

Исходя из вашего примера, но переписав каждую пару в .NET как 00, 11, 22 и т. Д. И переключив соответствующий байт Oracle, мы получим:

  • .NET:

    00112233445566778899AABBCCDDEEFF
    
  • Oracle:

    33221100554477668899AABBCCFFEEFF
    

Так что должно быть довольно легко написать код для переключения между соответствующими байтами. (На самом деле я уверен, что написал код для этой цели на предыдущей работе.)

Чтобы переключиться вокруг байтов, вам нужно просто позвонить Guid.ToByteArray() и new Guid(byte[]), чтобы вернуться к Guid.

РЕДАКТИРОВАТЬ: как это происходит, переключение выше точно , что делает конструктор Guid, когда вы передаете ему байтовый массив:

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

Печать:

00112233445566778899AABBCCDDEEFF
33221100554477668899aabbccddeeff

Это может значительно упростить переключение ... как вы получили начальные значения? Это просто "как они отображаются в Oracle"?

РЕДАКТИРОВАТЬ: Хорошо, вот пара функций преобразования - если у вас есть данные в виде текста, они будут преобразовывать в каждую сторону ...

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

}
7 голосов
/ 06 октября 2015

У меня была такая же проблема при хранении и чтении Guids из Oracle.

Ответ Джона верен для запросов, но если вашему приложению нужно хранить и читать Guids из Oracle, используйте функцию FlipEndian из этого потока:

.NET Преобразование собственного GUID

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

Перевертывание требуется только при чтении из Oracle.

При записи в Oracle используйте Guid.ToByteArray () как обычно.

Я потратил СЛИШКОМ много времени, пытаясь выполнить эту простую задачу.

Стив

5 голосов
/ 26 февраля 2014

Если вам нужно преобразовать GUID в RAW из PL / SQL , можете использовать эту функцию:

/*
    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;
1 голос
/ 03 сентября 2011

Просто всегда используйте ваш стандартный GUID в .NET ...

Если вы хотите вставить GUID в Oracle, вы просто вызываете Guid.ToString ( "N") и передаете эту строку в Oracle (в этом примере имя параметра 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;

Когда вы читаете RAW из Oracle, вы используете:

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

Затем вы можете подать возвращенные MyNETVal в new Guid (MyNETVal).

Таким образом, ваш код всегда имеет дело с форматом .NET, и переключение байтов происходит в Oracle-DB ... вы не добавляете код к коду преобразования и можете сохранить код при сохранении кода при переходе на другие БД - просто измените SQL, и вы уже в работе ... SQL может стать проще с другими БД, потому что некоторые из них следуют формату GUID Windows ...

...