MySQL中char(36)被認爲是GUID導致的BUG及解決方案

轉載地址:http://www.cnblogs.com/end/archive/2012/12/26/2834068.html

(近日正好有一個項目需要用到C#來操作MySQL數據庫,遇到這個奇怪的問題)

有時候在使用Toad或在程序中,偶爾會遇到如下的錯誤:

System.FormatException
GUID 應包含帶 4 個短劃線的 32 位數(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。
Stack Trace:
   在 System.Guid..ctor(String g)
   在 MySql.Data.Types.MySqlGuid.MySql.Data.Types.IMySqlValue.ReadValue(MySqlPacket packet, Int64 length, Boolean nullVal)
   在 MySql.Data.MySqlClient.NativeDriver.ReadColumnValue(Int32 index, MySqlField field, IMySqlValue valObject)
   在 MySql.Data.MySqlClient.ResultSet.ReadColumnData(Boolean outputParms)
   在 MySql.Data.MySqlClient.ResultSet.NextRow(CommandBehavior behavior)
   在 MySql.Data.MySqlClient.MySqlDataReader.Read()
   在 Quest.Toad.Db.ToadDataAdapter.InternalReadBackground()

原因是如果一個字段定義爲 CHAR(36), 則MySQL官方的連接器會將其當成 GUID 類型,有些情況下會要求你輸入(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)形式的字符串,否則會報錯。實際上,有時候 某個字段碰巧設爲可CHAR(36), 但是我們的本意並非當它是GUID。

(例如使用 MySqlDataAdapter 的 Fill 方法填充 DataTable時,就會拋出 Exception。可以使用連接器安裝後所附帶的 TableEditor 進行觀察,重複出這個Bug)

今天特意追蹤了一個MySql.Data中的代碼:發現MySqlCommand在Prepare的時候會調用Driver的PrepareStatement方法,會初始化ResultSet,會調用MySqlField.SetTypeAndFlags,其中有代碼如下:

 

if (((this.Type == MySqlDbType.String) && (this.CharacterLength == 0x24)) && !this.driver.Settings.OldGuids)
{
       this.mySqlDbType = MySqlDbType.Guid;
}

 

原因查明,解決方法是:將這個字段修改爲 VARCHAR(36) 或者 CHAR(40),總之,不是 CHAR(36) 就可以了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章