Quantcast
Channel: 黑暗執行緒
Viewing all articles
Browse latest Browse all 2311

【茶包射手日記】Managed ODP.NET在ASP.NET發生ORA-12154錯誤

$
0
0

故事要從前幾天學會讓ODP.NET查詢加速10倍的密技說起,原始問題在於Dapper查詢效能不佳,正想把新發現套用在Dapper上… 登楞!Dapper透過IDbConnection擴充方法提供功能,根本沒機會對OracleCommand或OracleDataReader動手腳啊!(抱頭)

打開Dapper原始碼,想研究有沒有地方傳FetchSize參數(還在裡面看到華麗的Emit特技,嘆為觀止),由於FetchSize非通用ADO.NET屬性,無功而返。

另一條路從環境設定著手,倒有點收獲:OLE DB時代,連線字串可加上FetchSize參數,但ODP.NET已不支援。要指定ODP.NET的FetchSize全域設定,可以使用Registry[參考]:HKLM\Software\Oracle\ODP.NET\ version\FetchSize,只是如此將影響該機器上所有使用ODP.NET的程式,執意調高擔心有副作用。最後,發現Managed ODP.NET可以經由config指定FetchSize[參考],將影響範圍縮小到特定應用程式,是較可行的做法。

開了一個小Console Application專案做測試,用NuGet抓了12.1.021的Oracle官方Managed ODP.NET[參考]:

安裝後,app.config自動補上相關設定:

直接執行,程式抱怨無法解析連絡ID:

ORA-12154: TNS: 無法解析指定的連線ID
ORA-12154: TNS:could not resolve the connect identifier specified.

上回提過 Managed ODP.NET 有一套尋找TNSNAMES.ORA的順序,決定使用規則2,在config手動補上TNS_ADMIN路徑參數,順便加上FetchSize:

<oracle.manageddataaccess.client>
<versionnumber="*">
  <dataSources>
    <dataSourcealias="SampleDataSource"descriptor="(DESCRIPTION…省略…) "/>
  </dataSources>
  <settings>
    <settingname="TNS_ADMIN"value="X:\Oracle\product\12.1.0\client\Network\Admin"></setting>
    <settingname="FetchSize"value="1048576"/>
  </settings>
</version>
</oracle.manageddataaccess.client>

補上TNS_AMDIN及FetchSize,Dapper果真變成光速前進。測試成功,如法修改使用Dapper的專案,由於為ASP.NET網站,原本web.config沒有<oracle.manageddataaccess.client>,我將測試成功的版本搬過去。以為需一併加上<configSections>的OracleInternal.Common.ODPMSetionHandler一起般去,結果加上反而會出現configSection重複定義錯誤,要移掉才OK。看起來web.config本來認得<oracle.manageddataaccess.client>,沒想太多,跑了網頁,卻一直冒出ORA-12154: TNS: 無法解析指定的連線ID錯誤。

反覆試了很久,結論是在web.config中放入的<oracle.manageddataaccess.client>沒發揮任何作用,改用IIS測試蒐集到新事證:當AppPool改用x64,web.config必須補上ODPMSetionHandler configSection,但可以成功解析連線ID,正確查詢DB。

拼湊以上線索,我想到一件事,應該是之前安裝Oracle ODAC32時,一併安裝了Managed ODP.NET, 導致32位元與64位元.NET設定不同。打開C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config,薑薑薑薑~

一開頭就有configSection設定

結尾則有鎖定4.121.1.0版號的TNS_ADMIN設定

這解釋了為什麼在Visual Studio,web.config不用加configSection也認得<oracle.manageddataaccess.client>(VS是x86環境)。但為什麼加入的TNS_ADMIN沒作用成謎。試著加入<dataSrouce alias>也無作用,感覺web.config的整個<oracle.manageddataaccess.client>設定被忽略。但又為什麼Console Application跑x86測試也會成功?

經過一番比對測試,找到關鍵差異。NuGet安裝Managed ODP.NET時一併加入bindingRedirect設定:

<runtime>
    <assemblyBindingxmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <publisherPolicyapply="no"/>
        <assemblyIdentityname="Oracle.ManagedDataAccess"
publicKeyToken="89b483f429c47342"culture="neutral"/>
        <bindingRedirectoldVersion="4.121.0.0 - 4.65535.65535.65535"
newVersion="4.121.2.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

將這段設定也加進web.config,Managed ODP.NET就順利找到TNSNAMES.ORA了。

回頭追了一陣子,每法對為何加入bindingRedirect將ODAC裝的4.121.1版Managed OPD.NET強轉為4.121.2能解決問題提出合理解釋,決定停損,將此謎團先歸入X檔案…


Viewing all articles
Browse latest Browse all 2311

Trending Articles