Managed ODP.NET簡介

Oracle Client版本問題困擾過很多次,之前由網友回饋得知Managed ODP.NET,一直沒深入研究過,直到今天完成評估,新武器一枚入手。

過去我們常用的Oracle.DataAccess(ODP.NET),骨子裡其實是走Unmanaged,得靠oci.dll那堆程式庫才能連上資料庫,因此安裝時必須一併安裝Oracle Client,而Unmanaged Oracle Client有32位元跟64位元之分,許多開發者還因此學會IIS Application Pool啟用32位元模式的技巧呢!加上Oracle.DataAccess.dll執行時需存取Oracle Client檔案,我還因此學會排除NTFS權限問題PATH環境變數等技巧,ODP.NET真的讓我成長好多… orz

由以上的血淚經驗,已足以說明Managed ODP.NET的長處:

  1. 不需要安裝龐大的Oracle Client,只用一個Oracle.ManagedDataAccess.dll就可搞定連線。
  2. 不必再為32位元跟64位元版本問題困擾,Oracle.ManagedDataAccess.dll的目標平台是Any CPU!(灑花)
    註:若程式啟用分散式交易,還需動用另一顆區分32及64版本的Oracle.ManagedDataAccessDTC.dll,但專案不需加入參照,Managed ODP.NET會自動載入正確版本

補充:除了Oracle.ManagedDataAccess.dll,若使用EF6+或Code First,專案需再多參照Oracle.ManagedDataAccess.EntityFramework.dll。

Managed ODP.NET可由Oracle官網下載取得,它被歸類為64-bit ODAC:

注意:Managed ODP.NET支援Entity Framework,但不提供設計階段支援,如果想在Visual Studio使用Entity Framework專案項目,仍須安裝32位元版ODAC with Oracle Developer Tools for Visual Studio,另一方面,開發者通常會用到SQL Plus或第三方Oracle資料庫工具,故開發環境仍會以ODAC 32位元為主,伺服器或大量部署的客戶端才是Managed ODP.NET展現威力的主戰場。

Managed版ODP.NET很小,只有2.53M,ZIP檔解壓縮可得到odp.net、network資料夾,readme.html安裝說明以及install_odpm.bat、uninstall_odpm.bat,為安裝及解除安裝批次檔。

一般會用install_odpm.bat c:\oracle both true安裝及註冊,install_odpm.bat有三個參數,第一個參數為安裝資料夾(將解壓縮內容複製到指定路徑再註冊),第二個參數為x86、x64、both三者擇一,第三個參數則決定是否要將元件加入GAC及在machine.config加入設定,如果要執行Entity Framework,請選true。

安裝動作很單純,下完指令瞬間完成,跟Unmanaged ODP.NET的安裝相比,是高鐵 vs 牛車的差別。

安裝完成後,下一步是換上作業環境專用的資料庫名稱設定檔,在本例中,TNSNAMES.ORA預設放在c:\oracle\network\admin\目錄。

要使用Managed ODP.NET時,專案必須做些修改,將Oracle.DataAccess參照改成Oracle.ManagedDataAccess,但OracleConnection、OracleCommand等用法都相同,程式碼幾乎[註]不需更動。(註:Managed ODP.NET與Unmanaged ODP.NET仍存在些許差異,不過依文件所列項目,我手上的程式應該都不用修改)

使用Visual Studio開發的專案,改用Managed ODP.NET的捷徑是透過NuGet下載:(該程式套件由Oracle官方提供,可安心服用)

前面提到,實務上Visual Studio開發機器多已安裝32位元ODAC(否則無法在專案中設計及修改Entity Framework模型),改由NuGet取得Managed ODP.NET後,取得TNS名稱的方式跟Unmanaged ODP.NET有所不同,傳統ODP.NET主要依賴Registry設定,而Managed ODP.NET則有自己解析TNS名稱的順序:參考

  1. .NET config裡dataSources區塊裡的設定(資料庫別名設定可以直接寫在config裡,如此連TNSNAMES.ORA都不需要)
  2. 由.NET config檔TNS_ADMIN設定所指路徑找到TNSNAMES.ORA
  3. EXE檔所在目錄下的TNSNAMES.ORA
  4. 環境變數%TNS_ADMIN%路徑下的TNSNAME.ORA
  5. 環境變數%ORACLE_HOME%\network\admin路徑下的TNSNAME.ORA

就這樣,只要一個Oracle.ManagedDataAccess.dll,就能連上Oracle,很棒吧?

【結論】

不需要安裝笨重的Oracle Client,不用擔心32位元跟64位元版本打架,.NET程式就能輕鬆連上Oracle資料庫,是Managed ODP.NET最大亮點。在伺服器只運行.NET程式或是要大量部署到客戶端的場合,改用Managed ODP.NET可大幅簡化Oracle Client部署作業,是很不錯的選擇!

【2015-04-01更新】

感謝同事Jean補充目前改用Managed ODP.NET可能欠缺的功能:(但未來應會陸續補上)

  1. XML相關功能
  2. 不支援的OracleDbType:XmlType、Array、Boolean、Object、Ref
  3. OracleAdvanceQueue(罕用)
  4. OracleBulkCopy
歡迎推文分享:
Published 31 March 2015 09:46 PM 由 Jeffrey
Filed under:
Views: 32,371



意見

# Larry said on 31 March, 2015 09:28 PM

感謝黑大

馬上用馬上見效 不是見笑XD

# 狐狸俊 said on 15 September, 2015 01:33 AM

請問黑大:

      這是 bug 嗎?以下程式會出現 ORA-01008: 部份變數未被連結 。

using (Oracle.ManagedDataAccess.Client.OracleConnection conn = ...)

{

conn.Open();

Oracle.ManagedDataAccess.Client.OracleCommand command = conn.CreateCommand();

command.CommandText = @"select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') as Data

from dual

where ('aa' = :p1 or :p1 is null)

and ('bb' = :p2 or :p2 is null)";

command.Parameters.Add("p1", "aa");

command.Parameters.Add("p2", "bb");

using (Oracle.ManagedDataAccess.Client.OracleDataReader reader = command.ExecuteReader())

{

while (reader.Read())

{

this.TimeLabel.Text = string.Format("database time: {0}", reader["Data"].ToString());

}

}

}

# Jeffrey said on 15 September, 2015 01:38 AM

to 狐狸俊, command.Parameters.Add(":p1", "aa");<=參數名稱要加上分號。

# 狐狸俊 said on 15 September, 2015 01:45 AM

to 黑大:

          我從沒加過也正常吶,無論是 SqlServer 的 @ 或 Oracle 的 :,

只要把 where 那一行改成 where ('aa' = :p1) 就正常執行了,所以以想請教你為什麼?

# Jeffrey said on 15 September, 2015 05:23 AM

to 狐狸俊, Sorry,先前沒看清楚你的程式,問題出在ODP.NET的OracleCommand.BindByName預設為false,意思是依Parameter在SQL語法的出現順序與Parameters.Add的加入順序配對,而不是依參數名稱。

如果SQL中:p1跟:p2各出現兩次( 如 'aa' = :p1 or :p1 is null),Paramters.Add時要加入兩次p1,兩次p2(名字不重要,順序要對)。如果想用變數名稱匹配,可將BindByName設為true(我習慣一律設true),如此行為就會跟SqlCommand一致。

補充:http://goo.gl/ELeCz3

# 狐狸俊 said on 15 September, 2015 05:53 AM

to 黑大:

          瞭解了,謝謝,獲益良多。

# Sam Zhong said on 06 October, 2016 02:06 AM

to 黑大:

我最近也使用了這個強大的元件,並配合Dapper來做Oracle資料存取。

但有個是關於Oracle語系 NLS_LANG 的設定問題,導制資料查詢後中文出現亂碼,這部份是否有比較標準的設定方式呢?

# Jeffrey said on 06 October, 2016 04:18 AM

to Sam Zhong, 問,DB欄位是用NVarChar2? 如果是用VarChar2,NLS_LANG要設成你資料連用的語系,如果是NVarChar2,經驗裡很少有問題,除了 ODP.NET + Dapper 的一個小Bug:blog.darkthread.net/post-2016-08-21-dapper-odpnet-unicode-issue.aspx

# Sam Zhong said on 07 October, 2016 12:24 AM

to 黑暗大:

感謝您的回應,目前暫時解法是客戶本機端提供OracleClient 環境,我程式直接改用OleOracle的連線提供者去連接資料庫。

Odp.Net的方法我再找時間測試,通常這種情形真的很罕見

你的看法呢?

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

5 + 3 =

搜尋

Go

<March 2015>
SunMonTueWedThuFriSat
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

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

文章典藏
其他功能

這個部落格


Syndication