问题的根本:
双关语意。
问题始于一个非常古老的 dBase 数据库,其中文本信息直接编码为DOS Cyrillic (CP-866),因为这还不够,所以每天晚上它也会被传输到 MySQL 数据库,我可以访问它.
我已经安装了 MySQL Providers 并使用 Entity Framework 连接到数据库,这是我的主要数据访问方法,然后出于实验原因使用纯 ADO.NET 也是如此。
在我尝试将所谓的CP-866值从数据库转换为UTF-8之前,一切都比预期的要好,如下所示:
var cp866 = Encoding.GetEncoding(866);
var utf8 = Encoding.UTF8;
string source = "some unreadable set of characters from the database";
byte[] cp866bytes = cp866.GetBytes(source);
byte[] utf8bytes = Encoding.Convert(cp866, utf8, cp866bytes);
string result = utf8.GetString(utf8bytes);
我用 EntityFramework 读过一次,用 ADO.NET 读过一次,结果相同。
由于当时未知和现在鲜为人知的原因,它没有用。在阅读了一些关于编码和字符串值的重要文章后,我确定由于字符串变量本身的性质,不可能将这种转换应用于数据库中 varchar 字段的字符串等效项。
几次键盘敲击之后,我终于通过使用 ADO.NET MySQL Provider 并通过将CONVERT(varcharColumn, Binary)添加到我正在测试的列来自定义我的查询来实现它。
从那时起,我使用上面的代码,唯一的区别是我已经从转换中获得了 cp866 字节数组。我最初打算做类似的事情,但 MySQL 提供程序无法直接从 varchar 字段读取字节,我也没有找到使用 Entity Framework 的方法。
是的,它有效,但即使对于我没有经验的自己来说,它也感觉不对。
问题:
1:我可以指定实体框架应该如何选择特定的字段吗?
我想以某种方式解释我心爱的 ORM,它应该在读取过程中将特定的 varchar 字段转换为二进制,而根本不返回字符串表示,因为它搞砸了一切。
2:有没有办法让 ADO.NET MySQL 提供程序获取 varchar 字段的字节,而无需先将其作为字符串拉出?
GetBytes 方法在与 varchar 一起使用时会引发异常,并且 MySQL 版本中缺少通常存在于 ADO.NET 提供程序中的 GetSqlBytes 方法。我真的不想在我需要正确阅读的每个字段上编写二进制转换。
3:额外问题:是否可以像我一样将 CP-866 编码的 varchar 字段读取为字符串,但这次正确地将编码更改为 UTF-8?
经过今天的阅读,我的脑海中仍然有很多关于编码主题的混乱。我仍然相信我可能遗漏了一些东西,并且可以从 cp-866 编码的 varchar 字段中读取字符串,例如:
string cp866EncodedValue = "Œ€„‹… Œ‹€„…Ž‚€ Šš…‚€"; //actual copy-pasted value
..然后将其转换为 UTF-8,同时记住数据库中的字段是用 CP-866 编码的。从我读过的内容来看,只要它在一个字符串中,它就是 unicode 并且字符串是不可变的。我已经尝试过获取它的 byre 数组表示,将其更改为 cp866,然后更改为 utf8,我尝试使用它,因为它本身就是 cp866,但没有成功。