- PR -

ADO.NETで大量にレコードを追加すると、メモリオーバーが発生

1
投稿者投稿内容
山田
常連さん
会議室デビュー日: 2004/11/22
投稿数: 25
投稿日時: 2005-03-24 16:19
いつもお世話になります。
初歩的な質問で申し訳ありません。

mdbデータ(約5000件)を、別のDBへ移行するシステムを.NETで開発しております。
参照HTMLにありますサンプルを元に、開発を進めていきましたが
処理が途中で止まってしまう現象が出ています。
内部的なエラーが発生している訳ではないので、メモリオーバーフローの可能性があります。

以下のようなソースを書いております。

1.Openメソッドを呼び出して、コネクションを張る。
2.key、column変数に、格納値を設定する。
3.Updateを呼び出して更新する。
4.Closeメソッドを呼び出して、コネクションを破棄する。

2〜3を、データ件数分ループさせておりました。
試しに、1〜4をデータ件数分ループさせると、停止することなく正常に全件登録が行えました。
2〜3の繰り返しでは、なぜメモリオーバーになってしまうのか原因が分かりません。
何かご存じの方がいらっしゃいましたら、ご教授頂きたく存じます。

using System;
using System.Data.OleDb;
using System.Data.Odbc;
using System.Collections;
using System.Data;

public class Test {

public object key;
public object column;

private OdbcConnection conn;
private OdbcCommand selectCmd;
private OdbcDataAdapter da;
private DataSet ds;
private DataTable dt;

public void Open(string pConnect)
{
string select = "SELECT * FROM TEST WHERE key = 0";

conn = new OdbcConnection();
conn.ConnectionString = pConnect;

selectCmd = new OdbcCommand();
selectCmd.Connection = conn;
selectCmd.CommandText = select;

da = new OdbcDataAdapter();
da.SelectCommand = selectCmd;
da.ContinueUpdateOnError = true;

ds = new DataSet();
da.Fill(ds, "TEST");
dt = ds.Tables["TEST"];
}

public void Update()
{
DataRow newRow = dt.NewRow();
newRow["key"] = key;
newRow["column"] = column;
dt.Rows.Add(newRow);

OdbcCommandBuilder cb = new OdbcCommandBuilder(da);
da.Update(ds, TABLE_NAME);
cb.Dispose();
newRow = null;
}

public void Close()
{
dt.Dispose();
ds.Dispose();
da.Dispose();
selectCmd.Dispose();
conn.Close();
conn.Dispose();
}
}
burton999
ぬし
会議室デビュー日: 2003/10/06
投稿数: 898
お住まい・勤務地: 東京
投稿日時: 2005-03-24 17:46
このソースって別DBに移行しているのでしょうか?
新しいレコードを登録してるように見えますが。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2005-03-24 17:48
引用:

試しに、1〜4をデータ件数分ループさせると、停止することなく正常に全件登録が行えました。
2〜3の繰り返しでは、なぜメモリオーバーになってしまうのか原因が分かりません。
何かご存じの方がいらっしゃいましたら、ご教授頂きたく存じます。



System.Data.Odbc を使用した場合、まったく同じ現象に遭遇したことがあります。

結局、その時は System.Data.OleD に変更することだけで回避してしまい、原因は突き止めませんでした (^^;;;


_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://www.hidori.jp/
// Microsoft MVP for Visual C#

[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2005-03-24 18:25 ]
山田
常連さん
会議室デビュー日: 2004/11/22
投稿数: 25
投稿日時: 2005-03-24 17:58
>burton999

申し訳ございません。
ご指摘通り、ODBC接続で、DBにレコードを登録する処理を行っております。
登録元と登録先が別DBなので、上記のような説明になっていました。
※今回の件と「移行」は、関係ありません。

>渋木宏明さん

情報、有り難うございます。
OleDbに変更・・・、変更にかかる工数も踏まえて検討したいと思います。

出来れば、ODBCのまま、回避出来る方法(ご指摘)があれば
有り難いのですが^^;
山田
常連さん
会議室デビュー日: 2004/11/22
投稿数: 25
投稿日時: 2005-03-24 18:02
申し訳ございません。
↑で、burton999さんを呼び捨てにしてしまいました(__)
nodera
大ベテラン
会議室デビュー日: 2003/09/08
投稿数: 200
投稿日時: 2005-03-24 18:07
こんにちは。

メモリーオーバーする原因は分かりませんが、このソースで気になった点があります。
たぶんTest.Update()メソッドが繰り返し呼び出されるんでしょうけど、繰り返すのは前半のdt.Rows.Add(newRow);までで、それ以降の処理はループ処理が終わった後に1回だけ呼び出せばいいと思います。

あと、コネクションは先にオープンしておいたほうがいいかな。
事前にオープンしておかないと、FillやUpdateが呼び出されるたびに、接続の開閉が行われてパフォーマンスに影響するかも。(コネクションプールが使えるドライバであれば、影響ないかもしれないけど)
山田
常連さん
会議室デビュー日: 2004/11/22
投稿数: 25
投稿日時: 2005-03-24 18:14
>noderaさん

ご指摘ありがとうございます!
下手なコードを丁寧に読んで下さったようで、有り難い限りです。
教えて頂きました対応、早速試してみたいと思います。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-03-25 22:06
引用:

noderaさんの書き込み (2005-03-24 18:07) より:

あと、コネクションは先にオープンしておいたほうがいいかな。
事前にオープンしておかないと、FillやUpdateが呼び出されるたびに、接続の開閉が行われてパフォーマンスに影響するかも。(コネクションプールが使えるドライバであれば、影響ないかもしれないけど)


 FillやUpdateの中のコマンド実行でコネクションがOpen/Closeされるなら、トランザクションがはれない(切れる)ような???
_________________
1

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