The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

解決 ASP.NET 跑在 x64 機器上無法連接 Oracle DB 的問題

今天又解決一個十分棘手的問題,我們有個專案原本在 x86 機器上開發 ( 資料庫採用 Oracle ),最近由於主機升級到 Windows 7 (x64) 後發現程式出問題,當在 Visual Studio 中按下 F5 進行測試除錯時完全無法連接到資料庫,而且一整個很沒道理,看看我如何解決這個棘手的問題吧。

我遇到的錯誤如下:

ORA-12154: TNS: 無法解析指定的連線 ID
ORA-12154:TNS:could not resolve service name

錯誤發生點是在「建立連線」的程式碼,只要 Open Connection 就會立即出錯。

這問題首先是出在我同事的身上,他主機在一個多月前換成 Windows Server 2008 (x64),而我是最近才換到 Windows 7 (x64),問題跟他一模一樣,因此也花了好多時間研究分析,直到剛剛跟黑大討論一番後終於給我找出解法。

先說說我電腦的安裝步驟與執行環境:

  • 安裝 Oracle Database 10g Client Release 2 (10.2.0.1.0) for Microsoft Windows (32-bit)
  • 設定 TNSNAMES.ORA 設定檔 ( 100% 肯定設定沒問題 )
  • 使用 SQL Plus 可以正常連線
  • 使用 SQL Developer 可以正常連線
  • 在 Visual Studio 中可以建置(Build)專案,建置/編譯後的組件部署到測試機也都沒問題
  • 在 Visual Studio 中使用內建的 ASP.NET 開發伺服器進行測試
  • 利用 Process Explorer 查看 WebDev.WebServer.EXE 程式,載入的組件都沒問題 (正確載入)
  • 利用 Prcoess Monitor 查看 WebDev.WebServer.EXE 程式,載入的 Oracle Client 相關參數檔路徑也都正確無誤

想破頭無法解決時,黑大建議我用最簡單的方式測試資料庫連線 (如下範例),雖然我自己已經測試數十遍了,但我還是不鐵齒,聽話的再測一次 ( 魔鬼總在細節裡 ):

using (OracleConnection cn = new OracleConnection(
    "Data Source=MyName;" +
    "Persist Security Info=True;" + 
    "User ID=user;" +
    "Password=pass"))
{
    cn.Open(); // 在此發生【 ORA-12154: TNS: 無法解析指定的連線 ID 】的錯誤
}

這時我才想到將 TNSNAME 的完整定義移到這裡試試看,請看如下範例:

using (OracleConnection cn = new OracleConnection(
    "Data Source=" +
    "  (DESCRIPTION =" +
    "    (ADDRESS_LIST =" +
    "      (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.0.245)(PORT = 1521))" +
    "    )" +
    "    (CONNECT_DATA =" +
    "      (SERVICE_NAME = MyName)" +
    "    )" +
    "  )" +
    ";Persist Security Info=True;User ID=user;Password=pass"))
{
    cn.Open(); // 在此時發生【 ORA-6413: 連線未被開啟 】的錯誤
}

這就神奇啦,錯誤訊息竟然不一樣,,中英文錯誤訊息如下:

ORA-6413: 連線未被開啟
ORA-06413: Connection not open

多一條錯誤訊息就多一條線索,對追 Code 絕對有幫助。 ( 好像在玩偵探遊戲一樣 ^^ )

這時就被我搜出一篇文章 ORA-06413: Connection not open. 答案就在其中,原來錯誤發生的原因原來是我的 ASP.NET 開發伺服器 ( WebDev.WebServer.EXE ) 執行檔的路徑有特殊字元導致:

C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\9.0\WebDev.WebServer.EXE

就是這該死的 (x86) 出現在路徑中,導致我的 ASP.NET 怎樣都無法連線到程式,為了驗證確定就是這問題,我試著利用 Process Explorer 找出 WebDev.WebServer.EXE 的啟動參數:

 利用 Process Explorer 找出 WebDev.WebServer.EXE 的啟動參數

並重新透過 cmd.exe (命令提示字元) 啟動 WebDev.WebServer.EXE,這時故意用「短目錄」啟動 ASP.NET 開發伺服器,如下指令:

"C:\PROGRA~2\Common Files\Microsoft Shared\DevServer\9.0\WebDev.WebServer.EX
E"  /port:5970 /path:"D:\XXXX\XXX\Website" /vpath:"/"

神奇的事這就樣發生,Oracle 資料庫竟然真的連上了!!

我的解決之道

  1. 改用 Windows 7 內建的 IIS7 進行網站執行與偵錯,不用 ASP.NET 開發伺服器了。Windows 7 內建的 IIS7 可新增多個網站,管理上也頗方便,不像 Windows XP 只能新增一個網站
  2. 改用 Visual Studio 巨集啟動 ASP.NET 開發伺服器偵錯,細節可參考我的另一篇文章:啟動 ASP.NET 偵錯模式的另一種比按下 F5 還快的方式

本次除錯心得

  • 不要鐵齒,越覺得不可能發生的地方越有可能是破案的核心關鍵!
  • 找個人聊聊你所遇到的錯誤,在互動、對話的過程中也許會想到一些你不曾想到的地方。
  • 「程式除錯」不但要有「經驗」更要有「創意」,當你擁有更多的「生活體驗」(程設的生活),相對的創意也就越多。
  • 熟悉多種除錯工具,並在工具間交互比對、驗證錯誤,一定可以看出一些端倪,但不要只是會「用」工具而已,而是要熟悉工具「背後的原理」,這樣才有助於你思考問題的本質問題背後的問題

相關連結