同事報案,某支在Windows 2003主機運作良好的轉檔程式,移至開發機執行更新Oracle資料庫時,中文變成問號。
比較原本執行正常的環境為Windows 2003 x86英文版 + Oracle Client 9207(真實世界永遠不乏這種與時代嚴重脫節卻維繫日常營運的中流砥柱啊),開發機則為Windows 7 x64英文版 + Oracle Client 12.1,二者存在不少差異。
寫了一段測試程式嘗試驗證問題,在我的機器(Windows 8.1 x64中文版 + Oracle Client 12.1)更新中文正常,移到同事的機器執行更新中文… 也正常。登楞!
只好回到轉檔程式用Visual Studio展開偵錯,在同事機器上確實能重現中文變問號現象。仔細比對轉檔程式與測試程式,這才發現測試程式用的是ODP.NET,而寫於民國初年的轉檔程式用的則是將被淘汰的System.Data.OracleClient。將測試程式也換成System.Data.OracleClient,有趣的事發生了,在我的電腦更新中文OK,在同事電腦則可重現中文變問號。
測試程式如下:
//using Oracle.DataAccess.Client;
using System.Data.OracleClient;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace OracleUpdateTest
{
class Program
{
staticvoid Main(string[] args)
{
TestOracle();
}
conststring cnStr = "Data Source=OracleServer;User Id=user;Password=ooxx;";
publicstaticvoid TestOracle()
{
System.Environment.SetEnvironmentVariable("ORA_NCHAR_LITERAL_REPLACE", "TRUE");
using (OracleConnection cn = new OracleConnection(cnStr))
{
cn.Open();
OracleCommand cmd = cn.CreateCommand();
cmd.CommandText = "UPDATE JEFFTEST SET NAME=N'中文測試' WHERE SEQNO = 1";
int r = cmd.ExecuteNonQuery();
cn.Close();
}
}
}
}
爬文求得一解,在連線字串加上"unicode=true"後問題排除。
依據文件說明,設定Unicode=true時,會指定 Oracle .NET Framework 資料提供者使用 UTF16 模式的 API 呼叫。很明顯這是一個 System.Data.OracleClient 專屬且只發生在特定Windows環境(Win7英文版?),由於 System.Data.OracleClient 已來日無多,不值得繼續深究,只記結論「System.Data.OracleClient 中文變問號,Unicode=true 連線參數不可少」,Case Closed。