【发布时间】:2011-04-20 15:37:57
【问题描述】:
我有一个 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 和 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) 我还可以使用哪些其他策略来提取这些 guid 并将它们存储在本地?
谢谢!
编辑:
这是我面前的一个例子。来自数据库:
从垃圾字符串产生的字符数组:
使用@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());
【问题讨论】:
-
char 数组是什么样的(16 个字符是什么)?预期的 GUI 是什么?
-
@Steve,我更新了我的问题。