[seasar-dotnet:1153] [DBFlute] 複数データソースに関して

takai [E-MAIL ADDRESS DELETED]
2008年 11月 21日 (金) 17:31:21 JST


初めまして、高井と申します。
複数 DB での DBFlute+Quill の利用について質問させてください。

今インスタンスが別々の複数の DB に接続するアプリケーションで
DBFlute の利用を考えております。
トランザクションは各 DB ごとに独立してかまいません。

動作環境は
  DB: SQLServer 2005 (3 台に別々の DB がある)
  Framework: .NET Framework 3.5
  DBFlute: 0.8.5
です。


DBFlute のページに記述されている複数 DB 利用時の手順に従って
ソースの自動生成まではできたのですが、プログラムがうまく動作しません。
Behavior (Dao?) が利用するデータソースが適切に切り替わってくれず、
常に最初に定義されたデータソースを参照してしまいます。
複数 DB を利用する場合はさらに何か記述や特別なプログラミングが必要なの
でしょうか?


App.config は以下のようにしていて、DS1 への接続ができていることから
データベースへの接続に関しては間違っていないと思います。
順序を DS2, DS3, DS1 の用にすると、DS2 へのアクセスだけうまくいきます。

...
  <quill>
    <dataSources>
      <dataSource name="DS1">
        <provider>SqlServer</provider>
        <connectionString>"Data Source=connstr1...."</connectionString>
        <class>Seasar.Extension.Tx.Impl.TxDataSource</class>
      </dataSource>
      <dataSource name="DS2">
        <provider>SqlServer</provider>
        <connectionString>"Data Source=connstr2...."</connectionString>
        <class>Seasar.Extension.Tx.Impl.TxDataSource</class>
      </dataSource>
      <dataSource name="DS3">
        <provider>SqlServer</provider>
        <connectionString>"Data Source=connstr3...."</connectionString>
        <class>Seasar.Extension.Tx.Impl.TxDataSource</class>
      </dataSource>
    </dataSources>
  </quill>
...

ソースはわけあって出せませんが、簡単な概略だけ記述します。
Inject された複数の Behavior を呼んでいるだけです。

protected DS1sBhv ds1bhv = null;  // DS1 を利用する Bhv
protected DS2sBhv ds2bhv = null;  // DS2 を利用する Bhv
protected DS3sBhv ds3bhv = null;  // DS3 を利用する Bhv

...
ds1bhv.SelectList(cond1); // これは通る
ds2bhv.SelectList(cond2); // ここでエラー DS1 を利用している
ds3bhv.SelectList(cond3);

例外をキャッチして詳細を見てみると、DS2 から取得したコネクションを介して
DB にアクセスすべきなのに DS1 のままでした。
SQL を投げてからテーブルがないために例外が発生しているようです。
XxxS2DaoInterceptor の cmd.Execute で例外が発生していて、
    // - - - - - - - - - -
    // Execute sqlCommand!
    // - - - - - - - - - -
    object ret = null;
    try {
        ret = cmd.Execute(invocation.Arguments);
    } catch (Exception e) {
        if (e.GetType().Equals(typeof(NotSingleRowUpdatedRuntimeException))) {
            throw new KSysEntityAlreadyUpdatedException((NotSingleRowUpdatedRuntimeException)e);
        }
        throw;
    } finally {
        PostprocessConditionBean(invocation, cb);
    }
e は NotSingleRowUpdatedRuntimeException ではないので上位にそのまま例外があがってきています。


自動生成されたソースを見ると、データソース名を記述している部分がなかっ
たので、XxxS2DaoSetting の DataSourceName プロパティを追記しました。
すると、ログにはデータソースを設定した(「SetDataSource=DS2」のようなログ)
旨の記述が出るのですが、利用されるデータソースは切り替わりませんでした。
結局テーブル名が見つからないため SQLException が発生してしまいました。

強制的にデータソースを切り替えてやると動きますが、これだと DI のありが
たみがない気がします。
トランザクションがどうなるのか…

protected DS1sBhv ds1bhv = null;
protected DS2sBhv ds2bhv = null;
protected DS3sBhv ds3bhv = null;
protected SelectableDataSourceProxyWithDictionary proxy = null;
...
ds1bhv.SelectList(cond1);
proxy.SetDataSourceName("DS2");
ds2bhv.SelectList(cond2);
proxy.SetDataSourceName("DS3");
ds3bhv.SelectList(cond3);
proxy.SetDataSourceName(String.Empty); //こうすると DS1 にだけ接続可能に
ds1bhv.SelectList(cond1);
proxy.SetDataSourceName(String.Empty);
ds1bhv.SelectList(cond2);  // エラー

DataSource を設定するインタセプタあたりになにかあるのかと思ってますが、
探り切れませんでした。
なにか解決策が見つけられればと思います。
お忙しいところ申し訳ありませんが、ご回答の方よろしくお願いします。
-- 
Takai ICT 株式会社
高井朋幸 <[E-MAIL ADDRESS DELETED]>
TEL: 090-6192-6789
http://www.takaiict.com/


seasar-dotnet メーリングリストの案内