如何解析存储为 char(16) 的 Uuid?
我有一个 Firebird 数据库,它将 Uuid 值存储在 char(16) 字段中。在我的 C# 程序中,我需要检索这些值以便在后续查询中使用它们。但我从数据库返回的值是“垃圾”。 (例如 ¿ñ)êNµmÏc—ÝX
)我尝试了各种方法将数据读取为字节数组并使用它来创建本地 Guid
,但这还没有'我没有得到任何地方。我得到的最接近的是使用 Encoding.ASCII.GetBytes()
,它确实给了我一个“有效”guid,但它与数据库中的“真实”guid 不匹配。我知道它们不匹配,因为(1)数据库有一个 UDF,它将“垃圾”转换为人类可读的字符串,以及(2)当我手动将该人类可读的 guid 复制到我的应用程序中时,使用它创建一个新的本地Guid
,并在我的查询中使用该值,我得到了正确的结果。 (而从字节数组创建的 guid 不会产生正确的结果。)我还尝试了 IDataRecord.GetBytes() 但这导致了 InvalidCastException(“无法将类型为 'System.String' 的对象转换为类型”) 'System.Byte[]'。")
此应用程序使用由另一个不相关产品创建的数据库,我无法控制其结构,也无法使用存储过程等内容。我也无法使用我之前提到的 UDF,因为它们很快就会再见。可用的 UDF 显然是 UuidToString< 的简单包装器/a> 和 UuidFromString。我想我可以在我自己的代码中使用这些函数,但如果有另一种不涉及互操作的方法,我宁愿不这样做。
最终,我需要 guid 在如下所示的方法中工作:
protected DataTable QueryDataTable(string query, string paramName, Guid guid)
{
DataTable table = new DataTable();
IDbCommand command = CreateDbCommand(query);
if (command is FbCommand)
{
FbCommand fbCommand = (FbCommand)command;
fbCommand.Parameters.Add(paramName, FbDbType.Binary).Value =
guid.ToByteArray();
// Also tried passing in the byte[] generated by
// Encoding.Ascii.GetBytes.... didn't work.
//fbCommand.Parameters.Add(paramName, FbDbType.Binary).Value = guid;
FbDataAdapter adapter = new FbDataAdapter(fbCommand);
adapter.Fill(table);
}
return table;
}
问题:
(1) 为什么我使用字节数组创建 guid 的策略不能产生“正确”的 guid?
(2) 我还可以使用哪些其他策略来提取这些指南并将它们存储在本地?
谢谢!
编辑:
这是我面前的一个例子。从数据库:
从垃圾字符串生成的字符数组:
使用 @Alexei Levenkov 建议的策略,生成的 guid (1) 非常接近,但不完全正确 (2)。
(1): fca3120b-511e-4269-b88f-d053a34b3513
(2): fca3120b-5184-4269-b88f-d053a34b3596
某些垃圾字符串确实会正确显示,但这是一个不正确的示例。这就是我实现 Alexei 的建议的方式,因为我没有看到字符串的 Select 方法:
// table is a DataTable
List<byte> bytes = new List<byte>();
string blah = (string)table.Rows[0][0];
foreach (char c in blah.ToCharArray())
{
bytes.Add((byte)c);
}
Guid guid = new Guid(bytes.ToArray());
I have a Firebird database which stores Uuid values in a char(16) field. In my C# program, I need to retrieve these values in order to use them in subsequent queries. But the values I get back from the database are "garbage". (e.g. ¿ñ)êNµmÏc—ÝX
) I've tried various methods of reading the data as a byte array and using that to create a local Guid
, but that hasn't gotten me anywhere. The closest I've gotten was by using Encoding.ASCII.GetBytes()
which did give me a "valid" guid, however it doesn't match the "real" guids in the database. I know they don't match because (1) the database has a UDF which converts the 'garbage' into a human readable string and (2) when I manually copy that human readable guid into my application, using it to create a new local Guid
, and use THAT value in my queries, I get the correct results. (Whereas guids created from byte arrays do not yield correct results.) I also tried IDataRecord.GetBytes()
but that resulted in an InvalidCastException ("Unable to cast object of type 'System.String' to type 'System.Byte[]'.")
This application uses databases created by another, unrelated product and I have no control over its structure, nor can I use things like stored procedures. I also cannot use the UDF's I mentioned earlier because they are going bye-bye soon. The available UDF's apparently are simple wrappers around UuidToString and UuidFromString. I suppose I could use those functions in my own code, but I'd rather not if there's another way that doesn't involve interop.
Ultimately, the I need the guid to work in a method that looks something like this:
protected DataTable QueryDataTable(string query, string paramName, Guid guid)
{
DataTable table = new DataTable();
IDbCommand command = CreateDbCommand(query);
if (command is FbCommand)
{
FbCommand fbCommand = (FbCommand)command;
fbCommand.Parameters.Add(paramName, FbDbType.Binary).Value =
guid.ToByteArray();
// Also tried passing in the byte[] generated by
// Encoding.Ascii.GetBytes.... didn't work.
//fbCommand.Parameters.Add(paramName, FbDbType.Binary).Value = guid;
FbDataAdapter adapter = new FbDataAdapter(fbCommand);
adapter.Fill(table);
}
return table;
}
Questions:
(1) Why isn't my tactic of using a byte array to create a guid resulting in a "correct" guid?
(2) What other tactics might I use to extract these guids and store them as locally as such?
Thanks!
Edit:
Here's an example of what I've got in front of me. From the database:
Resulting char array from the garbage string:
Using the tactic suggested by @Alexei Levenkov, the resulting guid (1) is very close but not exactly correct (2).
(1): fca3120b-511e-4269-b88f-d053a34b3513
(2): fca3120b-5184-4269-b88f-d053a34b3596
SOME garbage strings do turn out correctly, but this is an example of one that does not. This is how I'm implementing Alexei's suggestion, as I didn't see a Select method for strings:
// table is a DataTable
List<byte> bytes = new List<byte>();
string blah = (string)table.Rows[0][0];
foreach (char c in blah.ToCharArray())
{
bytes.Add((byte)c);
}
Guid guid = new Guid(bytes.ToArray());
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Char(16) 看起来像 GUID 的字节表示。尝试将字符串的每个字符转换为字节数组,然后从中创建 GUID
对于反向转换,请使用 guid.ToByteArray() 并将其转换为具有 ASCII 编码的字符串。
Char(16) looks like byte representation of the GUID. Try converting each character of the string to a byte array and than creating GUID out of it
For reverse conversion use guid.ToByteArray() and convert it to string with ASCII encoding.
在 Firebird 2.5 中,您有内置函数可以生成 this
in Firebird 2.5 you have built-in function to make this
这个问题很老了,但我在使用 Firebird 2.0(没有内置 UUID 生成器)时遇到了类似的问题。
因此,上述代码的主要问题是参数类型(二进制)错误。它应该是 FbDbType.Char 或 FbDbType.Guid。下面是一个工作示例。
This question is pretty old but I just had similar problem, while working with Firebird 2.0 (no built-in UUID generator).
So, the main problem with the code presented above was wrong parameter type (binary). It should either be FbDbType.Char or FbDbType.Guid. Below is a working example.
插入 guid 值时,将它们传递到查询中,就像
读取时一样,您可以使用以下类更正 Firebird .NET 数据提供程序中解析错误的值:
注意:出现此错误时不要使用此类是固定的。
When inserting guids values, pass them in your query as
when reading, you can correct the badly parsed value from the Firebird .NET Data Provider using the below class:
Note: Do not use this class when this bug is fixed.