- PR -

OracleConnectionのDisposeについて

1
投稿者投稿内容
Nya
会議室デビュー日: 2009/04/14
投稿数: 3
投稿日時: 2009-04-15 00:25
いつも参考にさせていただいております。

Visual Studio 2005 C# ASP.NET
Oracle10g

現在、イントラ内のWebアプリ開発および保守をおこなっており、DB接続にはSystem.Data.OracleClientを使用しています。
実際には、プロパティとしてSQL、Parameterを渡しDataSetを返すメソッドをもつ
ラッパークラスを作成してDBとのやりとりをおこなっています。
(メソッド内でOracleConnection,OracleCommandをusingを使用して
インスタンス生成しています)

先日までは何の疑問もなくこのラッパークラスを使用していたのですが、
このほど別会社からの納品物を修正することになり、そこに定義されていた
DBアクセス用のラッパークラスを確認したところ下記のような作りになっていました。

OracleConnection、OracleCommandはメンバ変数として定義
コンストラクタ     : OracleConnection、OracleCommandのインスタンス生成
DataSetを返すメソッド : 生成したインスタンスを使用して処理
自前のCloseメソッド  : OracleConnectionのClose,Dispose
              OracleCommandのDispose

この内容だと自前のCloseメソッドの呼び忘れや処理中の例外でConnectionのClose、
Disposeがおこなわれないのではないかと思い納品元に問い合わせたところ、

・連続してSQLを実行するときにいちいち接続しなくていい
・規約として必ずCloseを書けばいい

といったような回答が来ましたが、いまいち釈然としません。
せめてこのクラスにiDisposableが定義されていれば使用する側で
usingを使用してインスタンス生成すればいいような気もするのですが・・・。

一般的にDBアクセス用のラッパークラスを作成するとしたら、Connection等の
Disposeはどのようにおこなうものなのでしょうか?漠然とした質問で申し訳
ないのですが、どなたか「自分はこうしているよ」等のアドバイスを頂けたら
幸いです。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2009-04-15 07:37
引用:

Nyaさんの書き込み (2009-04-15 00:25) より:
いつも参考にさせていただいております。

Visual Studio 2005 C# ASP.NET
Oracle10g

現在、イントラ内のWebアプリ開発および保守をおこなっており、DB接続にはSystem.Data.OracleClientを使用しています。
実際には、プロパティとしてSQL、Parameterを渡しDataSetを返すメソッドをもつ
ラッパークラスを作成してDBとのやりとりをおこなっています。
(メソッド内でOracleConnection,OracleCommandをusingを使用して
インスタンス生成しています)

先日までは何の疑問もなくこのラッパークラスを使用していたのですが、
このほど別会社からの納品物を修正することになり、そこに定義されていた
DBアクセス用のラッパークラスを確認したところ下記のような作りになっていました。

OracleConnection、OracleCommandはメンバ変数として定義
コンストラクタ     : OracleConnection、OracleCommandのインスタンス生成
DataSetを返すメソッド : 生成したインスタンスを使用して処理
自前のCloseメソッド  : OracleConnectionのClose,Dispose
              OracleCommandのDispose

この内容だと自前のCloseメソッドの呼び忘れや処理中の例外でConnectionのClose、
Disposeがおこなわれないのではないかと思い納品元に問い合わせたところ、

?連続してSQLを実行するときにいちいち接続しなくていい
?規約として必ずCloseを書けばいい

といったような回答が来ましたが、いまいち釈然としません。
せめてこのクラスにiDisposableが定義されていれば使用する側で
usingを使用してインスタンス生成すればいいような気もするのですが???。

一般的にDBアクセス用のラッパークラスを作成するとしたら、Connection等の
Disposeはどのようにおこなうものなのでしょうか?漠然とした質問で申し訳
ないのですが、どなたか「自分はこうしているよ」等のアドバイスを頂けたら
幸いです。



dispose については、過去にも何度も話し合われています。
基本的に、ファイナライザーがオーバーロードされて、ファイナライザーで破棄されていれば大丈夫です。
規約は絶対に守られる訳ではないので、守られなかった時にも安全であることを出来るだけ保証するよう、クラス ライブラリを作成します。その辺は、MSDN ライブラリに書かれています。

連続して云々について、もう少し突っ込んで聞いてみて下さい。再接続の時間が省けるという理由であれば、「接続プールが使われるので時間はかからない」と指摘してみて下さい(事前に調べておいて下さい)。また、「閉じずに再度開こうとしたら、どうなりますか?」とも。こういったテストは、開発元でされているべきですが、問い合わせ前に軽く試してみて、望ましい結果になるか、確認しておくのもいいでしょう。
Nya
会議室デビュー日: 2009/04/14
投稿数: 3
投稿日時: 2009-04-15 22:59
Jittaさん、回答ありがとうございます。

申し訳ありませんが1点教えてください。

引用:

基本的に、ファイナライザーがオーバーロードされて、ファイナライザーで破棄されていれば大丈夫です。



とはラッパークラスに~(クラス名)を実装し、最終的にそこで必ず破棄すれば大丈夫、ということでしょうか?

引用:

連続して云々について、もう少し突っ込んで聞いてみて下さい。再接続の時間が省けるという理由であれば、「接続プールが使われるので時間はかからない」と指摘してみて下さい(事前に調べておいて下さい)。また、「閉じずに再度開こうとしたら、どうなりますか?」とも。こういったテストは、開発元でされているべきですが、問い合わせ前に軽く試してみて、望ましい結果になるか、確認しておくのもいいでしょう。



こちらについては明日、接続プールについての指摘をしてみるつもりです。
接続プールの存在自体については知っていたのですが、接続の再利用?といった
漠然とした知識しかなかったため、今回を機にしっかり調べてみたいと思います。

ちなみに、「閉じずに再度開こうとしたら」についてはクラス内では何も意識され
ていませんでした。こちらで試したところ例外が発生していました。
テスト段階で潰せる話ではありますが、これは"ナシ"だと思いますので、含めて
指摘してみたいと思います。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2009-04-16 00:39
なんとなくおかしな方向にいってしまってる気がするんですが…
引用:

Nyaさんの書き込み (2009-04-15 22:59) より:
引用:

基本的に、ファイナライザーがオーバーロードされて、ファイナライザーで破棄されていれば大丈夫です。


とはラッパークラスに~(クラス名)を実装し、最終的にそこで必ず破棄すれば大丈夫、ということでしょうか?


Jittaさんがどのような意図で書かれたのか分かりませんが、少なくともここでの話題ではファイナライザで大丈夫というのはちょっと方向が違うでしょう。
普通にIDisposableを実装するのが親切であり適切だと思いますよ。
で、普通に考えれば、このクラスにファイナライザをさらに実装するのは間違いです。

引用:

ちなみに、「閉じずに再度開こうとしたら」についてはクラス内では何も意識され
ていませんでした。こちらで試したところ例外が発生していました。
テスト段階で潰せる話ではありますが、これは"ナシ"だと思いますので、含めて
指摘してみたいと思います。


どういう意味でナシでしょう?
普通にありで、むしろ適切な動作ではないかと思いますが…

あとはまあ、トランザクションの管理がどうなっているか、などが気にするべき点かなと思います。
接続を開いたままにするのはどちらかというとトランザクションの管理で意味があることの方が多いと思いますので。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2009-04-16 07:35
close(dispose)を書き忘れた場合…あ、中で使ってる dbconnection のファイナライザーで dispose されますね。
不要でした。ご指摘ありがとうございます。
Nya
会議室デビュー日: 2009/04/14
投稿数: 3
投稿日時: 2009-04-19 19:51
なちゃさん、ありがとうございます。
なかなか時間がとれず返事が遅くなってしまいました。

引用:

どういう意味でナシでしょう?
普通にありで、むしろ適切な動作ではないかと思いますが…

あとはまあ、トランザクションの管理がどうなっているか、などが気にするべき点かなと思います。
接続を開いたままにするのはどちらかというとトランザクションの管理で意味があることの方が多いと思いますので。



例外を発生させないため、一度接続をきって再接続、もしくは接続前にチェックして
エラーを返す、と考えていたのですがたしかに一度接続を切って、はトランザクション
管理としておかしいですし、エラー出力はそもそもプログラムレベルの誤りで出して
そまってもユーザはどうにもできないため、おかしな判断でした。

なちゃさんのおっしゃるように現在の形を適切としました。また、iDisposableについて
は開発元に実装、全呼び出し元の修正という形で依頼を出しました。

Jittaさん、なちゃさん、ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)