﻿# 解決 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)，問題跟他一模一樣，因此也花了好多時間研究分析，直到剛剛跟[黑大](http://blog.darkthread.net/)討論一番後終於給我找出解法。

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

-   安裝 [Oracle Database 10g Client Release 2 (10.2.0.1.0) for Microsoft Windows (32-bit)](https://www.oracle.com/database/technologies/oracle-database-software-downloads.html)
-   設定 TNSNAMES.ORA 設定檔 ( 100% 肯定設定沒問題 )
-   使用 SQL Plus 可以正常連線
-   使用 SQL Developer 可以正常連線
-   在 Visual Studio 中可以建置(Build)專案，建置/編譯後的組件部署到測試機也都沒問題
-   在 Visual Studio 中使用內建的 ASP.NET 開發伺服器進行測試
-   利用 [Process Explorer](http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx) 查看 **WebDev.WebServer.EXE** 程式，載入的組件都沒問題 (正確載入)
-   利用 [Prcoess Monitor](http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx) 查看 **WebDev.WebServer.EXE** 程式，載入的 Oracle Client 相關參數檔路徑也都正確無誤

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

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

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

```csharp
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.](http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/d578dfe3-5bc3-4bce-9b9e-85b2e9d2f5de) 答案就在其中，原來錯誤發生的原因原來是我的 ASP.NET 開發伺服器 ( WebDev.WebServer.EXE ) 執行檔的路徑有特殊字元導致：

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

就是這該死的 (x86) 出現在路徑中，導致我的 ASP.NET 怎樣都無法連線到程式，為了驗證確定就是這問題，我試著利用 [Process Explorer](http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx) 找出 **WebDev.WebServer.EXE** 的啟動參數：

 ![利用 Process Explorer 找出 WebDev.WebServer.EXE 的啟動參數](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/2345bab668964f34dfa9-image.png "利用 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 還快的方式](/post/2008/11/06/Quick-Attach-and-Detach-ASPNET-Debugger)

**本次除錯心得**

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

**相關連結**

-   [ORA-06413: Connection not open.](http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/d578dfe3-5bc3-4bce-9b9e-85b2e9d2f5de)
-   [Connecting to Oracle on 64-bit (x64) machine](http://social.msdn.microsoft.com/Forums/en-US/sqlintegrationservices/thread/ab662d63-6385-4f73-b27f-d526048f601f)
