有一段使用System.Data.OracleClient.OracleConnection連線資料庫的程式,在同時安裝Oracle 11.2g 32位元與64位元Client的機器執行。OracleCommand.ExecuteReader()及ExecuteNoQuery()執行正常,但試圖OracleConnection.BeginTransaction()時出現以下錯誤:

BadImageFormatException - An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)

BadImageFormatException訊息直指32 vs 64位元DLL匹配問題,用Process Monitor追查證實了這點。IIS Express試圖在32位元Oracle Client目錄下找尋oramts.dll,找不到後改在64位元Client目錄下找到oramts.dll並載入,接著就爆出32/64位元版本不符錯誤。

機器上雖然可同時安裝32及64位元Oracle Client,但只能裝一份Oracle Service For Microsoft Transaction Server,當初選擇安裝的是x64版本。不過,由這個結果來看,執行分散式交易所必須的oramts.dll會伴隨Oracle Service For Microsoft Transaction Server一起安裝,所以只好乖乖也安裝一次32位元版本。安裝過程中會出現OracleMTSRecoveryService已存在的訊息(因為已裝了64位元版),忽略即可。之後32位元bin目錄就有了oramts.dll,BeginTransaction()便不再傳回錯誤。

好景不常,不久後遇到另一個問題,當BeginTransaction()被包在TransactionScope中,會產生OracleConnection does not support parallel transactions錯誤。如下例:

using (TransactionScope tx = new TransactionScope())
{
    using (OracleConnection cn = new OracleConnection(cs))
    {
        cn.Open();
        cn.BeginTransaction();
    }
}

推測在TransactionScope範圍內開啟的OracleConnection已暗地啟動了Transaction模式,呼叫BeginTransaction()會造成重複啟動。

最後我採用的解決方式是透過檢查Transaction.Current == null偵測是否被包在TransactionScope中,避開重複啟動Transaction的問題。


Comments

Be the first to post a comment

Post a comment