.NETでIBM iのDBをつついてみる

# Powerで.NETをサポート開始
  
以前の記事で書いた通り、.NETがPowerで動くようになりました。

https://qiita.com/tom_m_m/items/9a729f462c0622a5ece3

Powerということで、一番身近な？DBといえば、IBM iで動いているDb2でしょう。
今回は、.NETからIBM iのDBにアクセスしてSelectを投げてみます。
IBM i上にはサンプルデータのTOKMSPを準備しています。

# 環境情報
- .NET環境
    - RHEL 9.1 
    - .NET 7.0.1
- IBM i
    - IBM i 7.5

# IBM i への接続

IBM i で動いている Db2 for i に対してODBCを使ってアクセスします。
手順としては、

1. IBM iの設定
    1-1. ODBC用サービスの起動確認 
2. ODBCドライバーの準備
    2-1. リポジトリーの登録
    2-2. ODBCドライバーのインストール
3. .NETアプリの作成
    3-1. ODBCパッケージの追加
    3-2. Program.cs の変更 
    3-3. ビルド
    3-4. 実行

## IBM iの設定
ODBCを使う際には、IBM i側でODBC用のサービスが起動している必要があります。

参考: 

https://www.i-cafe.info/column/serials/dekiruibmi_no8

まずは、サービスが起動しているか確認しましょう。
5250エミュレーターからWRKACTJOBを実行します。
画像のように、`QUSRWRK`の下で `QZDASOINIT`が動いていれば大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242652/061207f4-eb58-6344-158f-9d060ff15370.png)

もし、対象のサービスが起動していない場合は、`STRHOSTSVR *ALL` コマンドを実行してください。

## ODBCドライバー準備

### リポジトリーの登録
IBM i に接続するためのLinux用 ODBCドライバーはACS (Access Client Solution)のパッケージとして提供されています。
dnfのリポジトリーとして提供されるため、IBMで提供しているレポジトリーの定義をダウンロードします。
```
[root@rhel9-dotnet work]# curl https://public.dhe.ibm.com/software/ibmi/products/odbc/rpms/ibmi-acs.repo | sudo tee /etc/yum.repos.d/ibmi-acs.repo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   142  100   142    0     0    212      0 --:--:-- --:--:-- --:--:--   212
```

### ODBCドライバーのインストール
dnfでインストールできるようになったので、`ibm-iaccess.ppc64le` をインストールします。
```
[root@rhel9-dotnet work]# dnf install --refresh ibm-iaccess.ppc64le
サブスクリプション管理リポジトリーを更新しています。
IBM i Access Client Solutions Linux             2.2 kB/s | 1.5 kB     00:00
Red Hat Enterprise Linux 9 for Power, little en  18 kB/s | 4.5 kB     00:00
Red Hat Enterprise Linux 9 for Power, little en  16 kB/s | 4.1 kB     00:00
依存関係が解決しました。
================================================================================
 パッケージ   Arch     バージョン      リポジトリー                       サイズ
================================================================================
インストール:
 ibm-iaccess  ppc64le  1.1.0.27-1.0    ibmi-acs                           1.1 M
依存関係のインストール:
 unixODBC     ppc64le  2.3.9-4.el9     rhel-9-for-ppc64le-appstream-rpms  500 k

トランザクションの概要
================================================================================
インストール  2 パッケージ

ダウンロードサイズの合計: 1.6 M
インストール後のサイズ: 10 M
これでよろしいですか? [y/N]: y
パッケージのダウンロード:
(1/2): unixODBC-2.3.9-4.el9.ppc64le.rpm         492 kB/s | 500 kB     00:01
(2/2): ibm-iaccess-1.1.0.27-1.0.ppc64le.rpm     479 kB/s | 1.1 MB     00:02
--------------------------------------------------------------------------------
合計                                            691 kB/s | 1.6 MB     00:02
トランザクションの確認を実行中
トランザクションの確認に成功しました。
トランザクションのテストを実行中
トランザクションのテストに成功しました。
トランザクションを実行中
  準備             :                                                        1/1
  インストール中   : unixODBC-2.3.9-4.el9.ppc64le                           1/2
  scriptletの実行中: ibm-iaccess-1.1.0.27-1.0.ppc64le                       2/2
  インストール中   : ibm-iaccess-1.1.0.27-1.0.ppc64le                       2/2
  scriptletの実行中: ibm-iaccess-1.1.0.27-1.0.ppc64le                       2/2
  検証             : ibm-iaccess-1.1.0.27-1.0.ppc64le                       1/2
  検証             : unixODBC-2.3.9-4.el9.ppc64le                           2/2
インストール済みの製品が更新されています。

インストール済み:
  ibm-iaccess-1.1.0.27-1.0.ppc64le         unixODBC-2.3.9-4.el9.ppc64le

完了しました!
```

unixODBCの現在設定を確認してみます。
```
[root@rhel9-dotnet work]# odbcinst -j
unixODBC 2.3.9
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /root/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
```

ODBCの設定ファイルがあるドライバーのリストを表示すると、`IBM i Acces ODBC Driver 64-bit`の表示があります。
このドライバーがあれば、IBM iへ接続可能です。 
```
[root@rhel9-dotnet work]# odbcinst -q -d
[PostgreSQL]
[MySQL]
[MySQL-5]
[FreeTDS]
[MariaDB]
[IBM i Access ODBC Driver]
[IBM i Access ODBC Driver 64-bit]
```

## .NETアプリの作成
ドライバーの準備もできたので、.NETのアプリを作っていきます。 
今回は、コンソールアプリを作ってターミナル上にIBM iから取得したデータを表示します。
```
[root@rhel9-dotnet work]# dotnet new console -o odbc_sample
テンプレート "コンソール アプリ" が正常に作成されました。

作成後の操作を処理しています...
/root/work/odbc_sample/odbc_sample.csproj を復元しています:
  Determining projects to restore...
  Restored /root/work/odbc_sample/odbc_sample.csproj (in 133 ms).
正常に復元されました。
```

### ODBCパッケージの追加
.NETでODBCを使えるようにするために `System.Data.Odbc` を追加します。
```
[root@rhel9-dotnet odbc_sample]# dotnet add package System.Data.Odbc
  Determining projects to restore...
  Writing /tmp/tmp38bKGn.tmp
info : X.509 certificate chain validation will use the system certificate bundle at '/etc/pki/ca-trust/extracted/pem/objsign-ca-bundle.pem'.
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/lib64/dotnet/sdk/7.0.101/trustedroots/timestampctl.pem'.
info : Adding PackageReference for package 'System.Data.Odbc' into project '/root/work/odbc_sample/odbc_sample.csproj'.
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/system.data.odbc/index.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/system.data.odbc/index.json 646ms
info : Restoring packages for /root/work/odbc_sample/odbc_sample.csproj...
info :   GET https://api.nuget.org/v3-flatcontainer/system.data.odbc/index.json
info :   OK https://api.nuget.org/v3-flatcontainer/system.data.odbc/index.json 160ms
info :   GET https://api.nuget.org/v3-flatcontainer/system.data.odbc/7.0.0/system.data.odbc.7.0.0.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/system.data.odbc/7.0.0/system.data.odbc.7.0.0.nupkg 822ms
info :   GET https://api.nuget.org/v3-flatcontainer/system.text.encoding.codepages/index.json
info :   OK https://api.nuget.org/v3-flatcontainer/system.text.encoding.codepages/index.json 601ms
info :   GET https://api.nuget.org/v3-flatcontainer/system.text.encoding.codepages/7.0.0/system.text.encoding.codepages.7.0.0.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/system.text.encoding.codepages/7.0.0/system.text.encoding.codepages.7.0.0.nupkg 1369ms
info : Installed System.Data.Odbc 7.0.0 from https://api.nuget.org/v3/index.json with content hash siwu7NoCsfHa9bfw2a2wSeTt2c/rhk3X8I28nJln1dlxdW3KqhRp0aW87yH1XkCo9h8zO1qcIfdTHO7YvvWLEA==.
info : Installed System.Text.Encoding.CodePages 7.0.0 from https://api.nuget.org/v3/index.json with content hash LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==.
info : Package 'System.Data.Odbc' is compatible with all the specified frameworks in project '/root/work/odbc_sample/odbc_sample.csproj'.
info : PackageReference for package 'System.Data.Odbc' version '7.0.0' added to file '/root/work/odbc_sample/odbc_sample.csproj'.
info : Writing assets file to disk. Path: /root/work/odbc_sample/obj/project.assets.json
log  : Restored /root/work/odbc_sample/odbc_sample.csproj (in 6.28 sec).
```

### Program.csの変更
作成したProgram.csはこちらです。
アクセス先やユーザー情報をお持ちの環境に設定することで使用できます。
また、変数`DbCommand.CommandText`にSQL文を入れることで任意のDB操作が可能です。
今回作成したプログラムでは、 `SELECT * FROM DEMOLIB.TOKMSP` を設定しています。
サンプルデータのTOKMSPをSelectで取得してみます。

``` c#:Program.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Odbc;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // Replace connection string with your IBMi systems credentialss
            string MyConString = "DRIVER={IBM i Access ODBC Driver 64-bit};" +
		    "SYSTEM=<アクセス先>;" +
		    "UID=<ユーザー>;" +
		    "PWD=<パスワード>;";

            // Open a Database Connection
            OdbcConnection DbConnection = new OdbcConnection(MyConString);
            DbConnection.Open();

            OdbcCommand DbCommand = DbConnection.CreateCommand();

            // Select rows from a table qiws.qcustcdt on IBMi
            DbCommand.CommandText = "<DDLの記述>";
            OdbcDataReader DbReader = DbCommand.ExecuteReader();

            // Display the retrieved data to the console
            int fCount = DbReader.FieldCount;

            Console.Write( ":" );
            for ( int i = 0; i < fCount; i ++ )
            {
                String fName = DbReader.GetName(i);
                Console.Write( fName + ":" );
            }
            Console.WriteLine();

            while( DbReader.Read())
            {
                Console.Write( ":" );
                for (int i = 0; i < fCount; i++)
                {
                    String col = DbReader.GetString(i);
                    Console.Write(col + ":");
                }
                Console.WriteLine();
            }

            // Close the Database Connection
            DbReader.Close();
            DbCommand.Dispose();
            DbConnection.Close();
        }
    }
}
```

### .NET ビルド
.NETのビルドを行います。
```
[root@rhel9-dotnet odbc_sample]# dotnet build
MSBuild version 17.4.0+18d5aef85 for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
  odbc_sample -> /root/work/odbc_sample/bin/Debug/net7.0/odbc_sample.dll

ビルドに成功しました。
    0 個の警告
    0 エラー

経過時間 00:00:05.62
```
### .NETアプリの実行

最後に、実行してみます...
```
[root@rhel9-dotnet odbc_sample]# dotnet run
[root@rhel9-dotnet odbc_sample]# dotnet run
:TKBANG:TKNAKN:TKNAKJ:TKADR1:TKADR2:TKTIKU:TKPOST:TKTELE:TKGURI:TKNURI:TKZURI:TKUZAN:TKGEND:TKNYUK:TKSIME:
:01010:ｱｲ ﾘﾖｶﾝ             :阿井旅館　　　　　:東京都渋谷区　　　:桜ヶ丘３０        :02:150   :03-504-9293  :698500:4086300:6615600:1000000:1100000:880427:2:
:01020:ｱｲ ｺｳｷﾞﾖｳ           :阿井工業　　　　　:東京都渋谷区　　　:渋谷１－３　　　　:02:150   :03-535-5951  :452800:2713600:4483700:670000:1150000:880607:2:
:01030:ｱｲｶﾜ ｺｳｷﾞﾖｳ         :相川工業　　　　　:東京都世田谷区　　:若林４－２４　　　:06:154   :03-964-6406  :136200:243000:796600:110000:1120000:880619:1:
:01040:ｱｲ ﾘﾖｺｳｼﾔ           :阿井旅行社　　　　:東京都品川区　　　:東五反田１－１１　:01:140   :03-934-7946  :3028300:18083100:27670700:9000000:1200000:880402:4:
:01050:ｱｲ ｼﾖｸﾄﾞｳK.K        :阿井食品Ｋ．Ｋ　　:東京都荒川区　　　:荒川５－４２　　　:17:116   :03-360-6701  :541600:2697600:4279600:1300000:1350000:880121:1:
:01060:ｱｲ ｼﾞﾄﾞｳｼﾔ          :阿井自動車　　　　:東京都港区　　　　:芝公園１－２　　　:14:105   :03-860-2932  :541100:2819100:4599900:1400000:1250000:880525:5:
:01070:ｱｲｶﾜ ｶﾒﾗ            :相川カメラ　　　　:東京都新宿区　　　:四谷１－１６　　　:03:160   :03-354-3018  :367900:2011700:3914500:960000:1000000:880611:1:
:01080:ｱｲｶﾜ ｺｳｸｳK.K        :相川広告Ｋ．Ｋ　　:東京都渋谷区　　　:広尾３－９　　　　:02:150   :03-368-6366  :318000:1461700:2205800:290000:2000000:880214:2:
:01090:ｱｲｶﾜ ﾃﾞﾝｷK.K        :相川電機Ｋ．Ｋ　　:東京都北区　　　　:滝の川７－１７　　:14:114   :03-749-6271  :877100:4731400:7135500:940000:900000:880519:2:
```
無事、IBM iのDBにアクセスしてデータを取得できました。

ACSからもSelectしてみましたが、同じデータが取得できています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242652/bd64ff7d-8af1-3952-e9c0-8d43b07af781.png)