使用 Dapper 和 ODAC Managed Driver 無法寫入 Unicode 的問題
TLDR
- 問題情境:使用 Dapper 搭配 Oracle Managed Driver (ODAC) 寫入 Unicode 字符(如簡體中文)時,資料庫端出現亂碼。
- 根本原因:ODP.NET 的
DbType.String預設被對應至OracleDbType.Varchar2,而非支援 Unicode 的OracleDbType.NVarchar2。 - 解決方案:無法直接透過 Dapper 的
DynamicParameters設定OracleDbType,需實作自訂的IDynamicParameters類別來手動指定參數類型。
Unicode 寫入亂碼問題分析
什麼情況下會遇到這個問題:當開發者使用 Dapper 進行資料庫寫入操作,且目標欄位為 Oracle 的 NVARCHAR2 或 NCHAR 等 Unicode 格式欄位時。
在 Oracle 的 Managed Driver 中,DbType.String 被錯誤地對應至 OracleDbType.Varchar2,這導致在處理 Unicode 字元時發生編碼轉換錯誤,進而產生亂碼。即便在 Dapper 中手動設定 DbType.String 也無法解決,因為底層驅動程式的對應邏輯並未將其導向正確的 NVarchar2 型別。
透過反組譯檢查 Oracle.ManagedDataAccess.Core (版本 3.21.100) 可發現:
DbType.String對應值為 16。OracleDbType.NVarchar2對應值為 119。OracleDbType.Varchar2對應值為 126。
驅動程式內部邏輯強制將 DbType.String 映射至 OracleDbType.Varchar2,導致 Unicode 數據在寫入時遺失正確的編碼資訊。
 
自訂 DynamicParameters 解決方案
由於 Dapper 的 DynamicParameters 不支援直接指定 OracleDbType,開發者必須實作 SqlMapper.IDynamicParameters 介面,建立一個自訂的參數容器,以便將 OracleParameter 物件正確加入 IDbCommand 中。
以下為實作範例:
public class MyDynamicParameters : SqlMapper.IDynamicParameters {
private readonly Dapper.DynamicParameters dynamicParameters = new();
private readonly List<IDbDataParameter> dbDataParameters = new();
public void Add(string name, object value, DbType? dbType, ParameterDirection? direction, int? size) {
dynamicParameters.Add(name, value, dbType, direction, size);
}
public void Add(IDbDataParameter paramerter) {
dbDataParameters.Add(paramerter);
}
void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Identity identity) {
((SqlMapper.IDynamicParameters)dynamicParameters).AddParameters(command, identity);
foreach (IDbDataParameter p in dbDataParameters) {
command.Parameters.Add(p);
}
}
}使用方式如下:
using (IDbConnection conn = new OracleConnection(connStr)) {
conn.Open();
MyDynamicParameters parameters = new();
parameters.Add(new OracleParameter {
ParameterName = "Name",
Value = value,
OracleDbType = OracleDbType.NVarchar2
});
conn.Query(sql, parameters);
}透過此自訂類別,可以繞過 Dapper 預設的型別對應,確保參數以 OracleDbType.NVarchar2 格式傳遞至 Oracle 資料庫,從而正確處理 Unicode 字元。
異動歷程
- 2023-06-15 初版文件建立。
