iBATIS.NETからSQLを取得してDataAdapterで利用する方法

iBATIS.NETはiBATIS.NETのまま使うのが一番だと思うのですが、政治的な都合やら諸般の事情やらで表題のようなことを行ってみたので、覚え書き程度に書いておきます。以下は、iBATIS.NETを使う上であくまでイレギュラーなことですので、それをご承知の上でご覧下さい。

やりたいことは、SQLとDbCommandだけiBATIS.NETから取得して、SQLの発行はADO.NETのDataAdapterで行い、DataTableを取得するというものです。というわけで、以下のような段取りで行います。

  1. 動的なSQLについて、iBATIS.NETのSQLMapで作成したものから取得する。
  2. iBATIS.NETから取得したSQLと、パラメータとで、DbCommandを作成する。
  3. 作成したDbCommandをDataAdapterのSelectCommandに代入して、DataSetにFill()する。

これを実装したのが以下のコードです。

iBATIS.NETのソースコードに添付されているACCESSのMDBファイルに対してアクセスするようなコードを、NUnitで書いて動かしてみました。

[csharp]
// SQLMapの初期化
Assembly assembly = Assembly.GetExecutingAssembly();
Stream stream = assembly.GetManifestResourceStream(
"iBATISLabo.Config.SQLMap.config");
DomSqlMapBuilder builder = new DomSqlMapBuilder();
mapper = builder.Configure(stream);

// パラメータの作成
Hashtable entity = new Hashtable();
entity.Add("LastName", "Dalton");

// コネクション無しでSqlMapを作成する
ISqlMapSession session = new SqlMapSession(mapper);
// SQLをXMLから取得
IMappedStatement statement = mapper.GetMappedStatement("SelectAccountList");
// リクエストを作成する
RequestScope request = statement.Statement.Sql.GetRequestScope(statement, entity, session);
// DBCommandを作成する
statement.PreparedCommand.Create(request, session, statement.Statement, entity);

Debug.WriteLine("★ SQL取得 : " + request.PreparedStatement.PreparedSql);

// DataAdapterの作成とFillメソッドでのデータ取得

DataSet ds = new DataSet();
OleDbDataAdapter adpt =
new OleDbDataAdapter(request.IDbCommand.CommandText, mapper.DataSource.ConnectionString);
OleDbParameter orgParam = (OleDbParameter)request.IDbCommand.Parameters[0];
// DbParameterのコピー(そのままインスタンスをAddするだけだと例外がスローされる)
OleDbParameter newParam =
new OleDbParameter(orgParam.ParameterName, orgParam.OleDbType, orgParam.Size, orgParam.Direction, orgParam.IsNullable, orgParam.Precision, orgParam.Scale, orgParam.SourceColumn, orgParam.SourceVersion, orgParam.Value);
// パラメータの設定
adpt.SelectCommand.Parameters.Add(newParam);
// SELECT文の発行
adpt.Fill(ds);

Debug.WriteLine("★ DataTable 取得 : " + ds.Tables[0].Rows.Count + " 件");

// 取得したデータの出力
foreach (DataRow row in ds.Tables[0].Rows) {
StringBuilder stb = new StringBuilder();
foreach (object value in row.ItemArray) {
if (stb.Length > 0) stb.Append(" | ");
if (value != null) {
stb.Append(value.ToString());
}
}
Debug.WriteLine("★ 取得レコード : " + stb.ToString());
}
[/csharp]

まず13行目にあるように、SqlMapperSessionを作成します。ここでは特にコネクションをオープンする必要はなく、単純にSqlMapperSessionのインスタンスだけあれば大丈夫です。

次に15行目で、XMLファイルに記述されたSQLのMappedStatementを取得します。

さらに17行目でRequestScopというクラスのインスタンスを取得します。このクラスのメンバに、PreparedStatementや、DbCommandのプロパティがあり、これをパラメータとしてiBATIS内部では最終的なSQLが実行される仕組みになっています。

そして19行目でDBCommandを作成します。ここで、Dynamicタグの記述が展開されて、最終的なSQLやパラメータが作成されます。

25行目以降は、作成したSQLとDBCommandを使って、DataAdapterでSQLを発行しています。30、31行目でOleDbParameterを再度作り直しているのは、既にOleDbParameterCollectionにAddされているOleDbParameterを別のDbParameterCollectionにAddすると例外になるためです。
http://msdn.microsoft.com/ja-jp/library/50xtbfet(VS.80).aspx

.NETの場合は、DataSet/DataTable取り扱った方が、画面のコントロールなどに対してデータバインドするのにいろいろと都合がよいので、アーキテクチャによってはこの方法が役に立つかもしれません。

コメントを残す

メールアドレスが公開されることはありません。