只有累積,沒有奇蹟

2019年4月24日 星期三

[.NET] 當 Dapper 遇到 SQL uniqueidentifier Type

問題 
Dapper 的輕巧與容易上手程度是大家有目共睹的,在公司中大部分專案也是選擇 Dapper 
資料庫做存取資料的動作,近期接獲同事詢問在開發時透過 Stored Procedure 存取資料庫某個 Table 中欄位資料型別為 uniqueidentifier (GUID) 一直失敗,Error 錯誤訊息為  Object must implement IConvertible ,這篇就針對此案例作簡單紀錄與分享若是有不清楚或是錯誤的地方歡迎討論予糾正

解決方法 
首先先還原案發現場,代碼如下
// Query
public IEnumerable<MemberModel> GetAllMember(int countryCode)
{
    var parameters = new DynamicParameters();
    parameters.Add("@countryCode", countryCode, DbType.Int16);
    parameters.Add("@output", string.Empty, DbType.String, ParameterDirection.Output);

    return Query<MemberModel>("[dbo].[usp_Member_GetAllMember]", parameters).ToList();
}

protected virtual IEnumerable<T> Query<T>(string name, SqlMapper.IDynamicParameters parameters)
{
    IEnumerable<T> result;
    try
    {
 using (var connection = new SqlConnection(connectionString))
 {
   result = connection.Query<T>(name, parameters, commandType: CommandType.StoredProcedure);
 }
    }
    catch (Exception e)
    {
 logger.LogError(e, name);
 throw;
    }
 
    return result;
}

// Model
public class MemberModel
{
    public string ID { get; set; }
    public string Name { get; set; }
}
在資料庫所要存取的 Table 設計 ID 資料型態為 uniqueidentifier,執行以上代碼會發生錯誤訊息如下
2019-04-24 18:09:13.8418||ERROR|.ctor|[dbo].[usp_Member_GetAllMember] System.Data.DataException: Error parsing column 1 (ID=d27ee4a2-146c-43f7-afc5-4e6cafe262b3 - Object) ---> System.InvalidCastException: Object must implement IConvertible.
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at Deserializece44011c-705b-4af9-bbdd-7b47377c8cc6(IDataReader )
--- End of inner exception stack trace --- 
取得資料後在 parsing 欄位值時發生錯誤 (Error parsing),錯誤型別為System.InvalidCastException,也就是說有抓到欄位值為 d27ee4a2-146c-43f7-afc5-4e6cafe262b3,但在 Parse 的時候轉型別失敗,遇到此情況有兩種解決方式

調整回傳欄位
在目前此 Case 可以看到回傳型別物件 MemberModel 中的 ID 欄位為字串 String,因此將 SP ID欄位回傳型別由原本的 uniqueidentifier 改為字串,在 MSSQL 中可以使用 CAST and CONVERT 進行轉換的動作,如下 
select convert(nvarchar(36), ID) as ID

調整 Model
原先的欄位型態為 uniqueidentifier 對應到 C# 中就是 Guid 型別,因此有可能因為此 SP 回傳值有不能修改的情況,因此可以修改承接的 ModelName 對應的欄位 ID,由原先的 string 改為 Guid 類型,調整如下 
public class MemberModel
{
    public Guid { get; set; }
    public string Name { get; set; }
}
調整完畢之後,即可正常執行取得資料
Enjoy Coding !!

參考
CAST and CONVERT 

0 意見:

張貼留言

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com