从Oracle的RAW(16)转换为.NET的GUID

时间:2011-09-02 22:18:23

标签: c# oracle nhibernate guid s#arp-architecture

我在手动调试Guid值从.NET到Oracle的.NET应用程序时遇到了困难。

  • C#读取的位置:
    • 17D89D326C2142D69B989F5201288DBF
  • Oracle读到:
    • 329DD817216CD6429B989F5201288DBF

我如何能够手动调试,即从C#的GUID能够将该值粘贴到oracle查询中并获得正确的结果(反之亦然)?

4 个答案:

答案 0 :(得分:47)

如果查看十六进制数字所涉及的值(成对),您可以看到最后7个字节在两种情况下都是相同的,但前9个字节在一点上切换。

从你的例子开始,但是将.NET中的每一对重写为00,11,22等,并切换Oracle的相关字节,我们得到:

  • .NET:

    00112233445566778899AABBCCDDEEFF
    
  • 甲骨文:

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

}

答案 1 :(得分:7)

在从Oracle存储和阅读Guids时,我遇到了同样的问题。

Jon的回答对于查询是正确的,但如果您的应用需要存储和读取Oracle中的Guids,请使用此线程中的FlipEndian函数:

.NET Native GUID conversion

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

只有在从Oracle回读时才需要翻转。

写入Oracle时,正常使用Guid.ToByteArray()。

我花了太多时间试图完成这个简单的任务。

史蒂夫

答案 2 :(得分:5)

如果您需要从 PL / SQL GUID 转换为 RAW ,可以使用此功能:

/*
    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 :(得分:1)

只需在.NET中使用您的标准GUID ...

如果要将一些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;

当您从Oracle阅读RAW时,您使用:

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可以更简单地与其他数据库一起使用,因为其中一些数据库遵循Windows的GUID格式...