可遇不可求的Question之MySqlClient的Guid 类型的映射篇
关于 Guid 类型的映射
MySql 没有原生的 Guid 类型,一般使用 binary(16) 或者 char(36) 这两个类型。早期版本的 Connector/Net 将 binary(16) 自动映射成为 Guid 类型。从 Connector/Net 6.1.1 开始,binary(16) 不再被自动映射成为 Guid 类型,而选用 char(36)。通过连接字符串的 Old Guids = true 选项可使用旧的 binary(16) 映射,这个选项的缺省值是 false,即使用 char(36)。参考 21.2.6. Connector/NET Connection String Options Reference 。
string connectionString = "server=localhost;user id=user;password=pwd;database=db;character set=utf8;Old Guids=true";
遗憾的是,在最新的发布版本 Connector/Net 6.2.3 中,缺少像 Treat Tiny As Boolean=false 这样的开关,无法关闭从 char(36) 到 Old Guid 的自动映射。因此,当你的数据库中恰巧使用了 char(36) 这个类型且这个字段存了不是合法 Guid 格式的字符值(中间用短横线隔开的 32 个数字 ,即 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx),那么你的程序就会报错。空字符是一个常见的情况,我们最近的一个系统就是被这个害惨了。虽然,我们明确这个 char(36) 类型字段是存应用程序生成的 Guid,而且加了 NOT NULL 约束,但在其他应用程序(PHP实现)中由于种种不可修复的原因,偶尔会向这个字段入了空字符,导致现有应用程序(.NET实现)读取失败。更要命的是,这个错误是在 MySqlDataReader.Read() 方法发生的,异常堆栈如下:
System.FormatException: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xx
xx-xxxx-xxxx-xxxxxxxxxxxx).
at System.Guid..ctor(String g)
at MySql.Data.Types.MySqlGuid.MySql.Data.Types.IMySqlValue.ReadValue(MySqlPac
ket packet, Int64 length, Boolean nullVal) in E:\MySQL\mysql-connector-net-6.2.3
-src\MySql.Data\Provider\Source\Types\MySqlGuid.cs:line 234
at MySql.Data.MySqlClient.NativeDriver.ReadColumnValue(Int32 index, MySqlFiel
d field, IMySqlValue valObject) in E:\MySQL\mysql-connector-net-6.2.3-src\MySql.
Data\Provider\Source\NativeDriver.cs:line 648
at MySql.Data.MySqlClient.Driver.ReadColumnValue(Int32 index, MySqlField fiel
d, IMySqlValue value) in E:\MySQL\mysql-connector-net-6.2.3-src\MySql.Data\Provi
der\Source\Driver.cs:line 415
at MySql.Data.MySqlClient.ResultSet.ReadColumnData(Boolean outputParms) in E:
\MySQL\mysql-connector-net-6.2.3-src\MySql.Data\Provider\Source\ResultSet.cs:lin
e 272
at MySql.Data.MySqlClient.ResultSet.NextRow(CommandBehavior behavior) in E:\M
ySQL\mysql-connector-net-6.2.3-src\MySql.Data\Provider\Source\ResultSet.cs:line
210
at MySql.Data.MySqlClient.MySqlDataReader.Read() in E:\MySQL\mysql-connector-
net-6.2.3-src\MySql.Data\Provider\Source\datareader.cs:line 875
at LeoLab.MySql.GuidChar36Test.Program.Main(String[] args) in E:\LeoLab.MySql
\LeoLab.MySql.GuidChar36Test\LeoLab.MySql.GuidChar36Test\Program.cs:line 30
这个错误信息中没有包含是哪一列哪一行发生了错误,因此,当你的 SELECT 语言包含很多字段,结果集又比较大的时候,就晕菜了,不知道这个 char(36) 与 Guid 映射关系的就被搞得莫名其妙的了。
目前最快速的解决方法,是“曲线救国”:通过设置 Old Guids=true 启用 binary(16) 到 guid 的映射来间接禁用 char(36) 到 Guid 的映射。
此外,我修改了 Connector/Net 6.2.3 的源码,增加了一个类似 Treat Tiny As Boolean 的 Treat Char As Guid 选项类禁用 char(36) 到 Guid 的映射。大概修改如下:
1. MySqlConnectionStringBuilder 中增加属性 TreatCharAsGuid
01.
[Category(
"Advanced"
)]
02.
[DisplayName(
"Treat Char As Guid"
)]
03.
[Description(
"Should the provider treat CHAR(36) columns as Guid."
)]
04.
[DefaultValue(
true
)]
05.
[ValidKeywords(
"Treat Char As Guid"
)]
06.
[RefreshProperties(RefreshProperties.All)]
07.
public
bool
TreatCharAsGuid
08.
{
09.
get
{
return
(
bool
)values[
"Treat Char As Guid"
]; }
10.
set
{ SetValue(
"Treat Char As Guid"
, value); }
11.
}
2. MySqlField 类的 SetTypeAndFlags 方法中的判断 if (Type == MySqlDbType.String && CharacterLength == 36 && !driver.Settings.OldGuids) 中增加TreatCharAsGuid的判断
1.
if
(driver.Settings.TreatCharAsGuid && Type == MySqlDbType.String && CharacterLength == 36 && !driver.Settings.OldGuids)
2.
{
3.
mySqlDbType = MySqlDbType.Guid;
4.
}
这样我们在连接字符串中指定 Treat Char As Guid=false,char(36) 就不会被映射成为 Guid 了,而是普通 String 。
源码下载 MySqlConnectorNet6.2.3-TreatCharAsGuid.zip (308.80 kb)
可遇不可求的Question之MySqlClient的Guid 类型的映射篇的更多相关文章
- 可遇不可求的Question之导入mysql中文乱码解决方法篇
可遇不可求的Question之导入mysql中文乱码解决方法篇 先 set names utf8;然后 source c:\1.sql ?
- 可遇不可求的Question之INSERT … ON DUPLICATE KEY UPDATE 语法篇
MySQL 自4.1版以后开始支持INSERT … ON DUPLICATE KEY UPDATE语法,使得原本需要执行3条SQL语句(SELECT,INSERT,UPDATE),缩减为1条语句即可完 ...
- 可遇不可求的Question之flash的socket连接安全策略文件篇
flash的socket连接安全策略文件 最近公司做压力测试的时候,发现了一个问题.flash的socket客户端向服务端请求安全策略文件的时候,服务端负责回发策略文件的端口能连接上,但是没有响应 ...
- 可遇不可求的Question之MySQL系统变量interactive_timeout 与 wait_timeout 篇
mysql>show variables like '%timeout'; 打印结果如下: +----------------------------+-------+ | Variable_n ...
- 可遇不可求的Question之MySql4.0前版本不支持union与批量SQL提交
批量SQL提交 参考 21.2.6. Connector/NET Connection String Options Reference . Allow Batch true When true, m ...
- 可遇不可求的Question之SQLSERVER触发器不支持多行插入操作篇
描述: 我们经常遇到 insert table_a select * from table_b 这样的语句, 同时在表table_a中根据每一条新增的SQL语句,通过触发器来触发对应的一系列的后续操作 ...
- 可遇不可求的Question之Sqlserver2005文件组的迁移篇
Sqlserver2005 文件组的折腾 问题:由于数据庞大,我在数据库里面使用了分区表,建了很多文件组,一个分区对应一个文件组,一个文件组只有一个文件.我在建分区表的时候,在数据库属性里面“文件”选 ...
- 可遇不可求的Question之Mysql在不重启服务的情况下修改运行时变量篇
比方说在一些实际生产环境中,想改个MYSQL的配置,但是又不想停止服务重起MYSQL,有什么办法呢?使用SET命令可以做到,请看下面几个例子: 1.设置key_buffer_size的大小为10M. ...
- 可遇不可求的Question之error: Failed dependencies: MySQLconflicts 错误篇
error: Failed dependencies: MySQLconflicts 错误提示: error: Failed dependencies: ...
随机推荐
- Vue+DataTables warning:table id=xxxx -Cannot reinitialize DataTable.报错解决方法
问题描述: 使用DataTables来写列表,用vue来渲染数据,有搜索功能,每次点击搜索就会报错,如下图所示. 问题排查: 找了一系列原因,最后发现是我每次请求完数据之后都会添加分页功能,从而导致了 ...
- vim高级工能入门
一.多文件编辑 1.vim 1.txt 2.txt 3.txt同时打开3个文件在vim缓冲区, 命令模式下输入:n 切换到下一个文件,可以加!:n! 强制切换,之前那个没有保存,仅仅是切换. ...
- 盒子模型(Box Model)
盒子模型(Box Model) ■ 盒子模型——概念 在网页设计中常用的属性名:内容(content),填充(padding),边框(border),边界(margin),CSS 盒子模式都具备这些属 ...
- python验证码识别接口及识别思路代码
1,验证码识别接口代码 import json import base64 import requests def shibie(): data = {} path = "./img/&qu ...
- Tableau可视化绘图教程
https://www.w3cschool.cn/tableau/tableau_environment_setup.html
- MySQL千万级数据库查询怎么提高查询效率
在实际项目中,当MySQL表的数据达到百万级别时候,普通查询效率直线下降,而且当使用的where条件较多,其查询效率是让人无法容忍的.假如一个taobao订单查询详情要几十秒,可想而知的用户体验是多差 ...
- 有关在Eclipse中安装STS(Spring Tool Suite)的若干问题总结
1.之前说明 在网上找了很多安装的方法,每次在线安装总会出现各种各样的问题,本地安装也是出现同样的问题(后来发现是下载的包有问题) 还有其他问题(忘记截图了,上图来自网络),大概就是这些各种各样的错误 ...
- java之servlet学习基础(一)
这一阵子在学java三大框架.却在学习过程中发现前面的知识已经忘记了.所以决定写一篇博客来总结回顾之前的学习. 1.Servlet是什么? servlet是一个运行在服务器端的小应用程序.通过HTTP ...
- centos中病毒
嗯 很开中了病毒,,,而且这是第二次了.... 然后大佬说让我 crontab -l 一下 然后试了下 然后出来这个东东 执行下 crontab -r 这个 然后就crontab -l 就 ...
- Python第十七天 抽象类
from abc import ABCMeta, abstractmethod class A(metaclass=ABCMeta): 称 A 为抽象类 @abstractmethod def tes ...