- PR -

Disposeについて

1
投稿者投稿内容
daito
常連さん
会議室デビュー日: 2005/03/26
投稿数: 30
投稿日時: 2005-05-25 16:30
いつも参考にせて頂いています。
ASP.NETの開発をVB.NET及びODP.NETを使ってやっているのですが、
基本的な事について質問させてもらいます。

DataGridのDataSourceにセットする値ですが以下の手順で作成しています。

OracleDataAdapterにOracleのデータをセットしてから、それを、
DataSetにFillをした後に、さらにDataTableへ代入してから、それをDataSourceに
セットする値にしています。

Disposeですが、OracleCommand等は行っているサンプルは良くあるのですが、
OracleDataAdapter、DataSet、DataTableのDisposeを行っているサンプルはみかけないのですが、行う必要はないのでしょうか?

Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-05-25 21:08
 DataAdapterは、いらなくなったら解放してください。とはいえ、本当に解放が必要なのは、そこで参照しているコネクションです。ですから、コネクションが確実にdisposeされるなら、DataAdapterをdisposeする必要はないと思われます。

 DataSetやDataTableについては、私は必要ないと思っています。また、いついらなくなったかがわからないのではないでしょうか。
 DataTableのインスタンスを、DataSetに追加すれば、DataSetが生きている間、DataTableも生きていなければなりません。DataSetを、DataGridのソースに設定すれば、DataGridのレンダリングが終わるまでは、DataSetも生きていなければなりません。

 そういうものがあるので、様々なリミットによって、ワーカプロセスを再起動させる仕組みがあるのだと思います。

_________________
daito
常連さん
会議室デビュー日: 2005/03/26
投稿数: 30
投稿日時: 2005-05-26 10:52
ご返事ありがとうございます。
コネクションのdisposeについては、Oracleに関する記述は、専用のクラスファイルにまとめている為、Finalize()のイベントで行っています。但しこのイベントでよいのかは、心配なのですが..
(コネクションをコンストラクタで行っている為、oracleの実処理部分ではdisposeしていません。)

DataSetやDataTableについては、Webフォームでdisposeを考えていましたので、
やるならば、Page_UnloadかPage_Disposedあたりかなと考えていましたが、
これらのdispose行わないようにします。

ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2005-05-26 13:19
引用:


コネクションのdisposeについては、Oracleに関する記述は、専用のクラスファイルにまとめている為、Finalize()のイベントで行っています。但しこのイベントでよいのかは、心配なのですが..



必要になったらそのつど作って破棄したほうがいいです。

それと、DataSetやDataTableのDisposeについて。結論から言えばDisposeする必要はありません。
単純にDataSetやDataTableがIDisposableなのはSystem.ComponentModel.Componentを継承しているからです。しかし、これらはすべてManagedのはずなのでDisposeする必要はないはずです。
ただ、問題はここからなのですが、ComponentのDisposeの実装はたぶん

コード:

public class Component {
	...
	~Component() {
		this.Dispose(false);
	}
	public void Dispose() {
		this.Dispose(true);
		GC.SuppressFinalize(this);
	}
	protected virtual void Dispose(bool disposing) {
	}
}



こうなってます。となると、これだけでは破棄しなければパフォーマンス的に影響がでる可能性があります(Finalizeは一般的に重い処理)。
しかし、さらに複雑なのは

コード:

public class DataSet : Component {
	...
	public DataSet() {
		...
		GC.SuppressFinalize(this);
	}
}



DataSetの定義はたぶんこのようになっていることです。これによって、パフォーマンス的な影響はでないようにされているはずです。

ただ結局、かいてきたように「中身を知っているかドキュメントに明記でもしてないとDisposeが必要かどうかなんてわからない」ので、「必ずDisposeを呼ぶ」でもいいですよ。よんだからといって何か問題がでるものでもないですし。ちなみに呼ぶタイミングですが、普通は親コンポーネントと同期させる(System.Web.UI.PageならDisposedイベント?)のがいいです。
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2005-05-26 13:34
daitoさん、こんにちは。

引用:

コネクションのdisposeについては、Oracleに関する記述は、専用のクラスファイルにまとめている為、Finalize()のイベントで行っています。但しこのイベントでよいのかは、心配なのですが..


ODP.NET ではなく、.NET Framework Data Provider for SQL Server の話ではあるんですが、 「.NET Framework 開発者ガイド」-「.NET Framework Data Provider for SQL Server の接続プール」には、以下のような一文があります。

引用:

メモ クラスの Finalize メソッド内で Connection、DataReader、またはその他のマネージ オブジェクトの Close または Dispose を呼び出さないでください。終了処理では、クラスに直接所有されているアンマネージ リソースだけを解放してください。クラスがアンマネージ リソースを所有していない場合は、クラス定義に Finalize メソッドを含めないでください。



引用:

(コネクションをコンストラクタで行っている為、oracleの実処理部分ではdisposeしていません。)


接続を共有しよう、というわけですね。
この辺については今までも何度か話が出ていますが(例えばこの辺とか)、ADO.NET では、必要なときだけオープンして、処理が終わったらクローズする、というのが基本です。接続のプーリングは、殆どの場合、各データプロバイダがよろしくやってくれます。
オープン/クローズを繰り返す事によるパフォーマンス低下が心配なら、実測の上、判断して下さい。
1

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