关于 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 类型的映射篇的更多相关文章

  1. 可遇不可求的Question之导入mysql中文乱码解决方法篇

    可遇不可求的Question之导入mysql中文乱码解决方法篇 先 set names utf8;然后 source c:\1.sql ?

  2. 可遇不可求的Question之INSERT … ON DUPLICATE KEY UPDATE 语法篇

    MySQL 自4.1版以后开始支持INSERT … ON DUPLICATE KEY UPDATE语法,使得原本需要执行3条SQL语句(SELECT,INSERT,UPDATE),缩减为1条语句即可完 ...

  3. 可遇不可求的Question之flash的socket连接安全策略文件篇

    flash的socket连接安全策略文件   最近公司做压力测试的时候,发现了一个问题.flash的socket客户端向服务端请求安全策略文件的时候,服务端负责回发策略文件的端口能连接上,但是没有响应 ...

  4. 可遇不可求的Question之MySQL系统变量interactive_timeout 与 wait_timeout 篇

    mysql>show variables like '%timeout'; 打印结果如下: +----------------------------+-------+ | Variable_n ...

  5. 可遇不可求的Question之MySql4.0前版本不支持union与批量SQL提交

    批量SQL提交 参考 21.2.6. Connector/NET Connection String Options Reference . Allow Batch true When true, m ...

  6. 可遇不可求的Question之SQLSERVER触发器不支持多行插入操作篇

    描述: 我们经常遇到 insert table_a select * from table_b 这样的语句, 同时在表table_a中根据每一条新增的SQL语句,通过触发器来触发对应的一系列的后续操作 ...

  7. 可遇不可求的Question之Sqlserver2005文件组的迁移篇

    Sqlserver2005 文件组的折腾 问题:由于数据庞大,我在数据库里面使用了分区表,建了很多文件组,一个分区对应一个文件组,一个文件组只有一个文件.我在建分区表的时候,在数据库属性里面“文件”选 ...

  8. 可遇不可求的Question之Mysql在不重启服务的情况下修改运行时变量篇

    比方说在一些实际生产环境中,想改个MYSQL的配置,但是又不想停止服务重起MYSQL,有什么办法呢?使用SET命令可以做到,请看下面几个例子: 1.设置key_buffer_size的大小为10M. ...

  9. 可遇不可求的Question之error: Failed dependencies: MySQLconflicts 错误篇

    error: Failed dependencies: MySQLconflicts   错误提示: error: Failed dependencies:                       ...

随机推荐

  1. java 安装教程

    https://www.cnblogs.com/xuyangblog/p/5455381.html

  2. 使用C编程语言实现AVL树

    本文将介绍AVL树及其插入.删除操作,最后使用C编程语言实现基于平衡因子(balance factor)的AVL树. 什么是AVL树? AVL树(AVL tree)是前苏联计算机科学家Adelson- ...

  3. SDL2.0 vs2017环境配置

    到SDL的官网下载VC++的Development Libraries. 新建一个项目,进入属性窗口. VC++目录->包含目录加入include所在路径,库目录加入lib\x86所在路径. 链 ...

  4. MAC终端如何使用rar和unrar

    一.MAC具体安装见下面两个博客分享: Homebrew介绍和使用:https://www.jianshu.com/p/de6f1d2d37bf Mac 压缩 / 解压缩工具解决方案:https:// ...

  5. pandas的一些

    在具体谈及骚操作之前先捋一遍基本的统计特征函数 方法名 函数功能 所属库 sum() 计算数据样本的综合(按照列计算) pandas mean() 计算数据样本的算术平均数 pandas var() ...

  6. vue 利用原声input上传图片并预览并删除

    <template> <div class="com-upload-img"> <div class="img_group"> ...

  7. MySQL数据库时间查询

    /*当前时间加1毫秒*/ SELECT DATE_ADD(NOW(),INTERVAL 1 MICROSECOND); /*当前时间减1毫秒*/ SELECT DATE_ADD(NOW(),INTER ...

  8. win10无法访问服务器上的共享文件夹怎么设置,提示:你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问

    此问题需要修改Win10 网络策略 按window+R键输入gpedit.msc 来启动本地组策略编辑器. 依次找到“计算机配置-管理模板-网络-Lanman工作站”这个节点,在右侧内容区可以看到“启 ...

  9. sqlserv 配置 CLR

    转载地址:http://www.cnblogs.com/Brambling/p/8000911.html   //clr 配置 https://docs.microsoft.com/zh-cn/sql ...

  10. [记录]MySQL 查询无法导出到文件

    很多时候我们需要将数据导出到 xls文件, 然后交给数据分析师分析. 而这个查询数据+导出的动作,理应使用一个有只读权限的用户使用. 但查询某表时: select * from table ,此用户可 ...