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

kubo [E-MAIL ADDRESS DELETED]
2008年 11月 21日 (金) 17:48:54 JST


久保(jflute)です。

高井さん、こんにちは

> 今インスタンスが別々の複数の DB に接続するアプリケーションで

というのは、
「テーブル構造の違うDBが複数ある」
という認識でよろしいでしょうか?

よくあるのですが、「複数DB」と言った時に、
A. 「テーブル構造の違う(DBの種類も違うかも)別のDB」
B. 「テーブル構造が同じ負荷分散のための別のDB」
を混同することが多いので確認です。

個人的には「複数DB」というと基本的には「A」を想定するのですが...
以下とりあえず「A」を前提にお話します。

> DBFlute のページに記述されている複数 DB 利用時の手順に従って
> ソースの自動生成まではできたのですが、プログラムがうまく動作しません。

こちら、具体的にそのページはどこでしょうか?
(URLを頂けます?)

DBFluteで「複数DB」するときは、基本的に
DBFluteクライアントを複数作成します。

dbflute_abc/...
dbflute_def/...
mydbflute/dbflute-0.8.5

「ABC」用のDBFluteと「DEF」用のDBFluteと作成し、
DBFlute本体モジュールは同じものを利用します。
生成されるクラスも同じNamespaceではなく、
それぞれ独立したNamespaceに生成します。

DBFluteは上記のような構成になっていますでしょうか?

詳しくは、
https://www.seasar.org/svn/sandbox/dbflute/trunk/dbflute-multipledb-example
のreadme.txtをお読み下さい。
dbflute-multipledb-exampleは複数DBのExampleです。
(Java版ですが、考え方・構成はほとんど同じです)

また、「seasar-dotnet:1135」も複数DBの話題ですので参考になります。


> SelectableDataSourceProxyWithDictionary

もし「A」の場合は、基本的にSelectableDataSourceProxyWithDictionaryの
利用は不要のはずです。これは「B」のためのクラスです。


2008/11/21 takai <[E-MAIL ADDRESS DELETED]>:
> 初めまして、高井と申します。
> 複数 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 mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>


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