【问题标题】:Making strings that may include utf-8 characters safe for MySQL in C#.Net在 C#.Net 中为 MySQL 制作可能包含 utf-8 字符的字符串
【发布时间】:2018-09-10 20:52:25
【问题描述】:

我有一个用 C#.net 编写的程序,它可以下载我们的 Amazon.com 订单并将它们存储在我们的本地数据库中。

我遇到了一个问题,即购买产品的客户在地址中输入了 utf8 字符 (℅) - (\xe2\x84\x85)。这似乎是一件非常合理的事情,但是我的程序在遇到此命令时会卡住,直到我进行以下修复。

                        //get the Address2 subnode
                    XmlNode Address2Node = singleOrder.SelectSingleNode("ShippingAddress/AddressLine2");
                    if (Address2Node != null)
                    {
                        GlobalClass.Address2 = Address2Node.InnerXml;
                        //** c/o Unicode character messed up program.
                            if (GlobalClass.Address2.Contains("℅"))

                            {
                                GlobalClass.Address2 = GlobalClass.Address2.Replace("℅", "c/o");
                            // Console.WriteLine(GlobalClass.Address2.Substring(0,1));
                            }
                        GlobalClass.Address2 = GlobalClass.Address2.Replace("'", "''");
                    }
                    else
                    {
                        GlobalClass.Address2 = "";
                    }

显然,这只适用于这一领域和这一 utf8 字符。如果没有这个修复,当我尝试使用 Mysql 插入它时,我收到一条错误消息,基本上相当于我的 Mysql 语句中存在错误,当它被发送到 MySQL 时,它基本上是在说要插入一条记录像 '\xE2\x84\x85..." 这样的字符串加上字符串的其余部分。

显然,我无法控制亚马逊在送货地址字段中允许的内容,因此我需要考虑可能出现的任何奇怪字符,但我不知道该怎么做。我曾希望只允许在我的连接字符串 (charset=utf8;) 中使用 utf8 来修复它,但这并没有做任何事情 - 仍然有同样的错误。也许我缺乏 Google 技能,但我似乎无法找到一种方法来允许可能出现的任何奇怪字符,我不想等到有人输入它来修复错误。

更新:

发送“SET NAMES utf8”作为查询怎么样?这有点超出了我的 MySQL 知识,我不想搞砸任何事情,但这行得通吗?如果是这样,我拥有的所有使用该数据库的程序是否都需要发送相同的查询?

更新2:对于那些一直要求异常错误消息的人,它是:

'MySql.Data.MySqlClient.MySqlException'发生在 MySql.Data.dll 附加信息:不正确的字符串值:第 1 行的列“ShipAddressLine2”的“\xE2\x84\x85 Yo...”

更新 3:从这个讨论中:SET NAMES utf8 in MySQL? 我尝试发送“SET NAMES 'cp1250'”,我很惊讶地看到这允许插入通过 ℅ 字符。我收集到,也许如果在我检索信息之前,我在另一个 MySQL 查询之前将“SET CHARSET 'utf8'”作为查询发送来检索它,也许我会得到正确的字符?我很高兴它通过发送“SET NAMES 'cp1250'”查询来通过我的程序,但我想知道要使用什么编码集(CP1250 是东欧,虽然我们有来自全球的客户,但我们的大多数客户在美国)并确保在我更改所有程序以包含此之前这是正确的做法。有人吗?

【问题讨论】:

  • my program choked - 这并不能告诉我们很多问题是什么......是否引发了异常?有错误信息吗?
  • UTF-8 不是字符集,它是一种编码。您正在谈论的字符是 Unicode“关心”符号 (U+2105)。我假设它在呈现为 UTF-8 时会按照您所说的进行编码。您是否查看了 MySQL 文档以查看允许/不允许哪些字符。过去,我之前通过将字符串映射到字符串(例如“℅”到“c/o”)并使用循环映射 StringBuilder.Replace 来清理字符串。但是,这既乏味又缓慢。
  • 抛出异常。上面提到了一条错误消息,虽然很遗憾我没有写下来并且无法重新创建它。这是说我的 MySQL 语句中有一个错误,它是一个 INSERT 语句,并且不知何故它与这个包含“℅...”的送货地址字段有关。 MySQL 不喜欢 ℅ 字符,显示的实际错误消息显示它好像我正在尝试插入 'xE2\x84\x85...'。
  • 我的问题并不是关于错误。我修好了。我的问题是,是否有一种合理的方法可以使包含 U+2105 等字符的字符串安全地插入 MySQL 数据库。我假设对于那些必须从互联网上获取他们无法控制的数据并将其插入到自己的数据库中的人来说,这是一个常见的问题。
  • 您是通过字符串与值连接来构建插入语句还是使用参数化语句?

标签: c# mysql utf-8 amazon


【解决方案1】:

如果其他人遇到此问题,我首先通过在存储数据之前向服务器发送 MySQL 命令:SET NAMES 'latin1' 来避免错误。这允许存储任何 utf8 字符而不会导致 MySQL 错误(我用几个奇数字符对其进行了测试)。然而,这会将 utf8 字符以一种神秘的格式存储,所以我将在下面给出一个更好的答案:

在我当前的解决方案中,我编辑了 MySQL 表并更改了可能接收 utf8 数据的相关列的字符集。我将列的字符集更改为 utf8mb4,将列的排序规则更改为 utf8mb4_general_ci。这样可以正确存储数据,因此 utf8 字符是正确的。

另外,在设置连接字符串的时候,我加了charset=utf8mb4;。

string MyConString = "SERVER=*****;" + "DATABASE=******;" + "UID=********;" + "PASSWORD=*********;" + "charset = utf8mb4;" ;

尽管据我所知,无论我是否包含 charset= 参数,它都会将内容保存到相同的字段中。

【讨论】:

  • 这是一个糟糕的解决方案,以后会导致奇怪的事情发生。我知道的一个令人讨厌的事情是 MySQL 会错误地比较字符串。
  • 你能告诉我为什么将字符集设置为默认值会导致 MySQL 错误地比较字符串吗?你能给我一个我可以验证的例子吗?
  • 你假设我有一个 utf-8 数据库吗?我的数据库使用默认值,即 latin1(或 latin1_swedish_ci)。
  • E28485`` is a UTF-8 encoding, not latin1 nor cp1250 nor anything else, you really should store it into a CHARACTER SET utf8` 或utf8mb4 列开始。当然,latin1(或BINARY)可以“工作”用于存储,但它对任何阅读您的代码的人都是具有欺骗性的。
  • 这很有帮助,谢谢。我将列更改为 utf8mb4,这也避免了错误并正确存储数据。我已经改变了上面的答案。
猜你喜欢
  • 2018-08-18
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 2016-01-11
  • 1970-01-01
  • 2011-08-16
  • 1970-01-01
相关资源
最近更新 更多