@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

レコードの取得と更新について

投稿者投稿内容
CHIEL
会議室デビュー日: 2005/01/21
投稿数: 5
投稿日時: 2005-01-21 13:33
お世話になります。

C#.NETでのDBからのレコードの取得と更新について教えてください。


下記ソースの**********の部分で、
INSERT処理を行いたいのですが、接続が使用されているとの
エラーになります。

// reader.cs

using System;
using System.Data.SqlClient;

class Reader {
public static void Main() {

string connStr = "Server=(local)\\\\NetSDK;"
+ "Trusted_Connection=yes;"
+ "database=pubs";

string sqlStr = "SELECT pub_id, pub_name FROM publishers";

SqlConnection conn = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand(sqlStr, conn);

conn.Open();
SqlDataReader dr = cmd.ExecuteReader();  ----@

while (dr.Read()) {
Console.Write("{0},{1}\\n", dr["pub_id"], dr["pub_name"]);

   *****************************
         AAAテーブルにINSERT 処理を行いたい
   *****************************


}
dr.Close();
conn.Close();
}
}

1コネクションでOPENできる?SqlDataReaderは一つということなのですが
私の場合のように、@結果セットの1件を読み込んで、その値により
AAAテーブルにINSERT、そして、@結果セットから、次の1件を読みこんで
AAAテーブルにINSERT・・
という処理を行うような場合には、どのように組めばいいのでしょうか。
mso
ぬし
会議室デビュー日: 2003/12/04
投稿数: 496
お住まい・勤務地: 宮城
投稿日時: 2005-01-21 13:47
msoです。

エラーとは関係ありませんが、
Insert/Update/Deleteのサンプルソースがあります。

ご参考にください。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=16845&forum=7
CHIEL
会議室デビュー日: 2005/01/21
投稿数: 5
投稿日時: 2005-01-21 14:00
msoさん、お返事ありがとうございました。

知識がないので、憶測ですけど、
ExecuteNonQuery()だと、カーソル?を使わないので
開きっぱなしですよ〜というエラーはでず、
ExecuteReaderの場合は結果セットから
カーソルを使って、1件ずつ取得するので
出るのではないかと。。

このカーソルを開いたまま、
ExecuteNonQuery()で、INSERTできればなぁと思った次第です。

Os_
ベテラン
会議室デビュー日: 2003/04/16
投稿数: 77
投稿日時: 2005-01-21 14:07
Osです。

別のテーブルにINSERTするのであれば、
新たにSqlConnection、SqlCommandを生成する方法があるかと思いますが。
CHIEL
会議室デビュー日: 2005/01/21
投稿数: 5
投稿日時: 2005-01-21 14:35
Osさん、ありがとうございます。
早速、試してみました。
1件目は、正常にINSERTされました!!
お〜!!(^○^)

しかし、2件目になると、
System.ArgumentException:項目は既に追加されています。辞書のキー:"pub_id" 
追加されるキー:"pub_id"というエラーが出てしまいます。

// reader.cs

using System;
using System.Data.SqlClient;

class Reader {
public static void Main() {

↓↓↓↓一つ目のSqlConnection,SqlCommand↓↓↓↓
string connStr = "Server=(local)\\\\NetSDK;"
+ "Trusted_Connection=yes;"
+ "database=pubs";

string sqlStr = "SELECT pub_id, pub_name FROM publishers";

SqlConnection conn = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand(sqlStr, conn);

↓↓↓↓二つ目のSqlConnection,SqlCommand↓↓↓↓
string connStr = "Server=ALPHA02;Trusted_Connection=yes;database=pubs";
SqlConnection conn2 = new SqlConnection(connStr);
string sqlStr2 = "INSERT INTO AAA values(@pub_id,@pub_name)";
SqlCommand cmd2 = new SqlCommand(sqlStr2, conn2);
cmd2.Connection = conn2;

conn.Open();
conn2.Open();

SqlDataReader dr = cmd.ExecuteReader();  ----@

while (dr.Read()) {
Console.Write("{0},{1}\\n", dr["pub_id"], dr["pub_name"]);

cmd2.Parameters.Add("@pub_id", dr["pub_id"]);
cmd2.Parameters.Add("@pub_name", dr["pub_name"]);
cmd2.ExecuteNonQuery();

}
dr.Close();
conn.Close();
conn2.Close();
}
}

何がいけないのでしょう・・
CHIEL
会議室デビュー日: 2005/01/21
投稿数: 5
投稿日時: 2005-01-21 15:00
すみません、解決しました。
自分のコーティングミスでした。

ありがとうございました。
CHIEL
会議室デビュー日: 2005/01/21
投稿数: 5
投稿日時: 2005-01-21 15:16
たびたび、すみません。

結果セットを見て、INSERT、UPDATEの場合でしたら、
もう一つ、コネクションを張ればいけるかと思ったのですが、
また、SELECTとなると、またまた結果セットを見て〜〜の
ロジックが必要となります。そうすると、二つ目のコネクションも
使えなくなりますよね?
それって、まずいような気がするのですが・・
Nilpo
会議室デビュー日: 2005/01/06
投稿数: 5
投稿日時: 2005-01-21 16:47
現在の SqlDataReader を維持したまま挿入を行いたいのであれば、新たに接続を開く必要があります。
逆に、SqlConnection や SqlCommand を再利用したいのであれば、SqlDataReader から読み取った値を、一度コレクション等に格納して SqlDataReader を閉じ、その後に挿入を行えばいいかと思います。
接続が増えていくこと自体は問題ではないです。接続数、レコードのロック、メモリ使用量等、パフォーマンスを考慮して目的にあったコードを書けばいいかと思います。
あと、コード側で加工する必要がないのであればクエリで処理してしまうのも手です。

--
コード:
・接続を複数使用する
using (SqlConnection con = this.CreateConnection("..."),
       con2 = new SqlConnection("..."),
       ...,
       conN = new SqlConnection(...))
{
	using (SqlCommand cmd = new SqlCommand("...", con), insert = new SqlCommand("...", con2))
	{
		cmd.Connection.Open();
		insert.Connection.Open();
		using (SqlDataReader reader = cmd.ExecuteReader())
		{
			while (reader.Read())
			{
				insert.Parameters.Clear();
				insert.Parameters.Add(...);
				insert.Parameters.Add(...);
				insert.ExecuteNonQuery();
			}
		}
	}
}
・接続の再利用
using (SqlConnection con = new SqlConnection("..."))
{
	using (SqlCommand cmd = new SqlCommand("SELECT ...", con))
	{
		cmd.Connection.Open();
		ArrayList container = new ArrayList();
		using (SqlDataReader reader = cmd.ExecuteReader())
		{
			while (reader.Read())
			{
				container.Add(new Foo(reader[0], reader[1]));
			}
		}
		foreach (Foo foo in container)
		{
			cmd.CommandText = string.Format(commandFormat, foo.ID, foo.Name);
			cmd.ExecuteNonQuery();
		}
	}
}
・クエリ
INSERT INTO dest_table (id, [name]) SELECT id, [name] FROM src_table WHERE ...


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