Managed な ODP.NET で tnsnames.ora を参照する (Windows, Visual Studio 2015)

# Managed な ODP.NET で tnsnames.ora を参照する (Windows, Visual Studio 2015)

開発 PC の Visual Studio に ODP.NET 管理対象ドライバを Nuget で導入した場合、リモートのデータソース情報を定義した tnsnames.ora を探してくれなかった。

調べたことを備忘録として記録する。

## 問題

.NET Framework 4 向けのドライバを Visual Studio に Nuget で導入する。

```
PM> install-package Oracle.ManagedDataAccess
'.NETFramework,Version=v4.6.1' を対象とするプロジェクト 'Odp64Sample' に関して、パッケージ 'Oracle.ManagedDataAccess.12.1.24160719' の依存関係情報の収集を試行しています
DependencyBehavior 'Lowest' でパッケージ 'Oracle.ManagedDataAccess.12.1.24160719' の依存関係の解決を試行しています
パッケージ 'Oracle.ManagedDataAccess.12.1.24160719' をインストールするアクションを解決しています
パッケージ 'Oracle.ManagedDataAccess.12.1.24160719' をインストールするアクションが解決されました
パッケージ 'Oracle.ManagedDataAccess.12.1.24160719' をフォルダー 'C:\Users\xxx\documents\visual studio 2015\Projects\Odp64Sample\packages' に追加しています
パッケージ 'Oracle.ManagedDataAccess.12.1.24160719' をフォルダー 'C:\Users\xxx\documents\visual studio 2015\Projects\Odp64Sample\packages' に追加しました
パッケージ 'Oracle.ManagedDataAccess.12.1.24160719' を 'packages.config' に追加しました
'Oracle.ManagedDataAccess 12.1.24160719' が Odp64Sample に正常にインストールされました
```

アクセスする Oracle Database はリモートの 11g で、クライアントとなる開発 PC には、.NET Framework 2.0 向けの ODP.NET ドライバを使用するアプリを開発していたときの tnsnames.ora は導入されている。

この環境状の Visual Studio 2015、.NET Framework 4.6.1、VB.NET で、接続するだけのサンプルを動かすと、データソースが解決できずに `conn.Open` が失敗する。

```vbnet
Using conn = New OracleConnection("user id=scott;password=tiger;data source=xxx")
    Try
        conn.Open()
        MessageBox.Show("データベースに接続しました。")

    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
End Using
```

## 調べた内容

[Oracle® Data Provider for .NET開発者ガイド 12c リリース1 (12.1.0.1) Oracle Data Provider for .NETの構成](https://docs.oracle.com/cd/E49329_01/win.121/b72971/featConfig.htm)

の `dataSourcesセクション` は次のように説明している。

> 接続文字列のData Source属性で指定したデータソース・エイリアスは、次の優先順序で解決されます。
-  .NET構成ファイルの<oracle.manageddataaccess.client>セクションにあるdataSourcesセクション内のデータソース・エイリアス。
-  .NET構成ファイルのTNS_ADMINで指定した場所にあるtnsnames.oraファイル内のデータソース・エイリアス。
-  .exeと同じディレクトリにあるtnsnames.oraファイル内のデータソース・エイリアス。

つまり、アプリから接続文字列で指定したデータソースの実体を解決するには、次のいずれかが必要になる。

1. app.config (web.config?) の `dataSource` 要素に tnsnames.ora のデータソース定義と同じ内容を指定する。
2. app.config (web.config?) の `setting` 要素に、tnsnames.ora の置き場所を指定する。
3. tnsnames.ora を exe ファイルと同じフォルダに置く。

Nuget でインストールした私の環境には、app.config に要素 `<oracle.manageddataaccess.client>` が追加されていた。コレに `setting` 要素を追記すると以下になる。

```xml
<oracle.manageddataaccess.client>
  <version number="*">
    <settings>    <!-- 2. の指定 -->
      <setting name="TNS_ADMIN" value="%ORACLE_HOME%/network/admin" />
    </settings>
    <dataSources>    <!-- 1. の指定 -->
      <dataSource alias="SampleDataSource" descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=リモートのアドレス)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) "/>
    </dataSources>
  </version>
</oracle.manageddataaccess.client>
```

クライアントアプリケーションの接続文字列に `SampleDataSource` を指定すると、リモートのデータベースに接続できた。 3. は未確認。


また、これはオラクル社のドキュメントには見つけられなかったが、次の方法でも tnsnames.ora を見つけることができた。サポートされるかも未確認。

- 環境変数 `TNS_ADMIN` に tnsnames.ora のパスを設定する
- クライアントアプリケーションの接続文字列に次を指定する。  
`... Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=リモートのアドレス)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) ...`


## 参考

同文書、同項には、次の記述もあるのでクライアント PC に ODP.NET をインストールして回るなら、本トピックの問題は発生しないと考えられる、未確認。

>ODP.NET管理対象ドライバとOracleホームを一緒にインストールすると、TNS_ADMIN設定が自動的に.NET Frameworkのmachine.configファイル内に作成されます。TNS_ADMIN設定はディレクトリ<ORACLE_HOME>\Network\Admin\となるように設定され、ここがデフォルトのマシンの場所となってtnsnames.ora、sqlnet.oraおよびldap.oraの各ファイルがホスティングされます。



## 確認した環境

- 日本語 Windows 10 64 ビット
- Visual Studio 2015 Community 
- Oracle.ManagedDataAccess            {12.1.24160719}