使用Visual Studio 2012已經好一陣子,手上的專案也逐一改用VS2012維護開發。今天處理的專案剛好涉及Oracle,想當然爾,要用Entity Framework才是王道! 此時發現原先安裝的ODAC 11.2 Release 4,只支援到VS2010,在VS2012新增ADO.NET Entity Data Model時,Data source沒有"Oracle Database (Oracle ODP.NET)"可選,所幸Oracle已於9/11推出ODAC 11.2 Release 5,加入對VS2012的支援。

二話不說,立刻下載安裝!

安裝過程很順利,正要為Oracle按個讚之際,卻發現VS2012要新增ADO.NET Entity Data Model時還是沒有Oracle可選。想對照比較,還更進一步發現,在安裝完Release 5後,VS2010的Server Explorer要新增連線時,雖然可選擇Oracle Database (Oracle ODP.NET),但其【OK】鈕呈現灰色停用狀態,無法新增。(相關操作請參考前文) 按下【Test Connection】鈕,則會彈出錯誤: Unable to find the requested .NET Framework Data Provider.  It may not be installed.

我的推測是在安裝ODAC 11.2 Release 5後,某些設定被改壞了,不但VS2012沒法用Oracle EF,連VS2010原本可用的功能也壞了~

試著重新安裝Oracle Developer Tools for Visual Studio並無幫助(不過現在回想,我只試了重新安裝,沒有試過"先解除安裝再安裝一次",如果有朋友做過相同實驗,請再回報結果)。改由錯誤訊息下手,爬文後,對.NET DbProviderFactories機制多了一丁點了解,並在一番嘗試後終於解決問題。

[2012-10-31更新] 網友Dino回報"先移除ODAC 11.2 Release 4再安裝ODAC 11.2 Release 5,VS2010/VS2012均可順利使用無異常",在此感謝!

原來,.NET可以使用哪些Data Source,跟\Windows\Microsoft.net\Framework\vXXXX\Config\machine.config有關,在其中有一段DbProviderFatories宣告: (以下擷取自v2.0.50727\config\machine.config)

<system.data>
    <DbProviderFactories>
        <add name="Oracle Data Provider for .NET" invariant="Oracle.DataAccess.Client" description="Oracle Data Provider for .NET" type="Oracle.DataAccess.Client.OracleClientFactory, Oracle.DataAccess, Version=2.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
        <add name="SqlClient Data Provider" invariant="System.Data.SqlClient" description=".Net Framework Data Provider for SqlServer" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
        ....省略...
</DbProviderFactories>
</system.data>

在ODT或EF Data Model要新增連線時,Data Source可選項目看起來與其宣告的項目吻合。而我們可用以下程式列出所有DbProviderFactory加以驗證: [參考來源]

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                System.Data.DataTable dt =
                    DbProviderFactories.GetFactoryClasses();
                for (int i = 0; i < dt.Rows.Count; i++)
                    Console.WriteLine("{0}: {1}", i.ToString(), 
                                      dt.Rows[i][2].ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            Console.Read();
        }
    }
}

(注意: 因為Visual Studio本身是32位元.NET程式,記得以上程式Target要設成x86,顯現結果才會與Visual Studio IDE所見一致)

使用VS2012以.NET x86 Console Application執行上述程式,果真沒有Oracle.DataAccess.Client!

0: System.Data.Odbc
1: System.Data.OleDb
2: System.Data.OracleClient
3: System.Data.SqlClient
4: System.Data.SqlServerCe.4.0

檢查\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config,卻發現其中只有SQL Client CE一個項目: (但為什麼列舉結果中還是有Odbc, OleDb, SqlClient, System.Data.OracleClient? 我查到一篇討論,MSFT Support表示4.0起另有機制可動態取得.NET Framework內建的SqlClient及OracleClient,不需依賴machine.config設定)

    <system.data> 
    <DbProviderFactories>
        <add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>
    </DbProviderFactories>
    </system.data>

推敲此處應放入.NET 4.0版本的Oracle.DataAccess.Client設定,因此我手動補上(紅字部分):

<system.data>
<DbProviderFactories>
<add name="Oracle Data Provider for .NET" invariant="Oracle.DataAccess.Client" description="Oracle Data Provider for .NET" type="Oracle.DataAccess.Client.OracleClientFactory, Oracle.DataAccess, Version=4.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
<add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>
</DbProviderFactories>
</system.data>

加入後重跑前述DbProviderFactory列舉程式,Oracle.DataAccess.Client便已名列其中,在重新啟動VS2012後,Data Source選擇視窗已有Oracle Client可選,ADO.NET Entity Data Model也能順利新增Oracle EF Data Model囉~


Comments

# by Dino

報告黑暗大,我是ODAC 11.2 Release 4之後重新安裝ODAC 11.2 Release 5,結果一切正常,2010和2012都可正常使用~

# by Jeffrey

to Dino, 請問你是先移除R4再重新安裝R5嗎?

# by Dino

不好意思,居然漏字了。是的,我是先移除R4後再重新安裝R5的

# by Jeffrey

to Dino, 感謝熱心回報,已經您的經驗加註於本文。

# by wayne

請問按照您的方式安裝後,在sqlDataSource的設定資料源,測試連線出現『找不到必要的.Net Framework Data Provider,可能尚未安裝』,不知道哪裡未設定,請您指導,謝謝,(Win8+VS2012)

# by Jeffrey

to wayne, 關於問題細節的資訊太過有限,難以判斷。文中有提到一些檢查方式,如果有較多方面的測試及觀察所得,大家較能幫忙推敲。

# by GuoXIII

請問您, 公司的oracle版本太舊了(7.3 or 7.4), 連線的作業系統目前侷限在win xp 32bits, 而因為資料量龐大也暫不考慮更新資料庫系統... 使用win7 64bits系統有什麼方法可以連得上嗎? 謝謝您

# by Jeffrey

to GuoXIII, 據我所知,9iR2以後的Client已連不上Oracle Server 7.x ( 參考:https://community.oracle.com/thread/2429379 ),Windows只能裝10.2以上的Oracle Client,二者夾擊下,看來無解,我想只能寄望有3rd Party Libray能不經Oracle Client直接連線Oracle,但這是條冷僻小路,或許有其他地雷要面對。

# by GuoXIII

了解 非常謝謝您

# by GuoXIII

請教, 若我在windows 64bits上裝VM虛擬xp 32bits系統,藉由VM xp連線到舊版oracle取值,這樣的話會有什麼缺點嗎? win7 <-->VM XP <--> oracle 感覺上如果行得通,windows 64bits系統尚被微軟支援更新,會比較安全,又可藉由VM連線到oracle取值,不知道這樣行不行得通?

# by Jeffrey

to GuoXII,如果是我,我應該也會採行類似的做法:弄一台x86 OS(VM或實體機)在上面跑自己寫的中介服務(WCF或Web API),要存取舊版Oracle一律透過中介服務。缺點是原本用到ODP.NET查詢的程式都要改寫(如果當初有抽出Interface或資料存取元件,工程會小一點),另外,若存取頻繁中介服務的負擔過重,則還要考慮多裝幾台並設定負載平衡機制。

# by guoxiii

謝謝!

Post a comment