【茶包射手日記】老 Bug 新感受之 ODP.NET 版本問題

同事報案。某個使用 Managed ODP.NET 的測試網站吐出以下錯誤
Error: The type initializer for 'OracleInternal.Common.ProviderConfig' threw an exception.

同事一度懷疑跟 ODP.NET 版本有關,但依經驗,如為版本問題錯誤訊息會確指出所需元件全名、版號等資訊。為調查問題,我直接在 IIS主機現場撰寫 Tets.aspx 偵錯,測試程式一用到 new Oracel.ManagedDataAccess.Client.OralceConnection() 就吐出以下錯誤:

Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.
Parser Error Message: An error occurred creating the configuration section handler for oracle.manageddataaccess.client: Could not load file or assembly 'Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Source File: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config    Line: 14

錯誤訊息提到 Oracle.ManagedDataAccess.Client 4.121.1.0,鐵證如山,證實是 Managed ODP.NET 版本不相容,而machine.config 的第 14 行正是

<section name="oracle.manageddataaccess.client" type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />

由此推測,問題出在該主機有安裝 Managed ODP.NET 4.121.1,而專案升級到 ODP.NET 4.121.2,但在 web.config 遺漏 bindingRedirect 將所有 Managed ODP.NET 版本導向 4.121.2的設定,解析 web.config 時先引用了 machin.config,提到需要 4.121.1 版,但 bin 目錄下卻是 4.121.2 版,便爆出版本不符錯誤。

但有個問題是,為什麼專案程式抛出的錯誤訊息跟 Test.aspx 測試不同?追查出錯的程式片段,發現它是透過 Autofac 取得資料來源物件,屬於動態載入,推測是造成導致錯誤訊息不同的原因,使用以下程式剖析 InnerException,可證明 configuration section handler 錯誤外層又包一層OracleInternal.Common.ProviderConfig 錯誤:

<%@ Page Language="C#" %> 
<% 
    //var cn = new Oracle.ManagedDataAccess.Client.OracleConnection("...");
 
    var dp = MyAutofacFactory.Resolve<IEntityDataProvider>();    
    try 
    { 
        var cn = dp.CreateConnection(); //其中邏輯為 new OracleConnection後回傳 
    } 
    catch (Exception ex) 
    { 
        Response.Write(ex.Message); 
        Response.Write("<hr />"); 
        Response.Write(ex.InnerException.Message); 
    } 
%>

測試結果如下:

•    The type initializer for 'OracleInternal.Common.ProviderConfig' threw an exception.
•    An error occurred creating the configuration section handler for oracle.manageddataaccess.client: Could not load file or assembly 'Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040) (C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config line 14)

最後回到「為什麼第一時間沒能看出版本不相容?」

問題出在該專案 try catch 了資料庫讀寫作業,但發生錯誤時只抛出 Exception.Message,卻沒保留或顯示 InnerException 或 Callstack 資訊(如要省事,改取 Exception.ToString() 即涵蓋所有重要資訊 ),遺失可供追查辦案的重要線索,是實務上使用 try  catch 易被疏忽的細節,此一經驗提供大家參考。

歡迎推文分享:
Published 10 February 2018 08:15 AM 由 Jeffrey
Filed under: ,
Views: 2,666



意見

沒有意見

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<February 2018>
SunMonTueWedThuFriSat
28293031123
45678910
11121314151617
18192021222324
25262728123
45678910
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication