あなたは確かにif
を使用することができますが、エラーなしで、このような場合にはwhile
を使用することができるはずです。 if
に変更するだけですが、複数の行を持つことができる場合に同じことをすると、同じエラーが発生します。したがって、例外が発生した理由を調べることが重要です。
のは、あなたのコードを見てみましょう:
while (myReader.Read())
{
info = myReader.GetString("info");
...
をこれまでのところは良いです。
/**
* Write the relevant info in the LOGS
*/
connection.Close(); <---------- :S
connection.Open(); <---------- if I don´t do this I got some problems with the connection!!!!
ああ!あなたはあなたの "いくつかの問題"を修正しましたが、あなたはそれらの "いくつかの問題"が何であったか知っていましたか?実際には、あなたがwhile
を壊したことがあります。私は、「これまでのところは良い」と述べた時点で
が、これはあなたが起こっているものです:
- あなたは接続オブジェクトを持っています。それが開いています"。
- データリーダーオブジェクトがあります。接続からデータを取得しています。
IDbCommand.ExecuteReader
(http://msdn.microsoft.com/en-us/library/68etdec0.aspx)の仕様では、この接続はそのリーダーで使用されています。明示的に、またはusing
ブロックに割り当てられた場合にはDispose()
によって、Close()
を読者に呼び出すまで、接続を閉じる以外は何もすることはできません。
厳密には、これは必ずしも真実ではありません。特定の実装では、インターフェイスの約束以上(インターフェイスの署名に従って、またはドキュメントに従って)、常にあなたに与えることが許可されています。多くの実装では、Read()
がfalseを返すと接続を「解放」します(SQLServer 2005にはMultipleActiveResultSets=True
オプションがあります)。これにより、同じ接続で同時に複数のデータエリアを同時にサポートできます(欠点があります)。それでも、規則のこれらの緩みは、私たちが現在の接続で間違いなく行うことができるのはClose()
です。
この理由から、cmdLog.ExecuteNonQuery()
を呼び出そうとすると、エラーメッセージの形で「何らかの問題」が発生しました。これは、使用中の接続を使用しようとしたためです。
このように、接続で行うことができた唯一のことを行うことで、これを「固定」してから、もう一度開きます。すべての目的と目的のために、あなたは真新しいつながりを持っています!
でも、while
にループバックすると、myReader.Read()
が再び呼び出されます。このメソッドは、接続からのデータストリームを読み込み、falseが返された場合(結果がない場合)、またはストリームから読み込んだ内容に基づいて一連のフィールドを作成します。
しかし、あなたはその接続をクローズしています。つまり、クローズド接続から読み込みしようとしているだけで、実行できないため、例外が発生します。
while
をif
に変更すると、Read()
操作に戻ったことはないので、コードは再び機能します。
しかし、複数の行を持つ結果セットでこれを行う必要がある場合はどうしますか?
MARSを使用できます。それについてはhttp://msdn.microsoft.com/en-us/library/h32h3abf%28v=vs.80%29.aspxを参照してください。率直に言って、何かがそれ以上のものを得ない限り、私はそれを避けるだろう。それはあなたがそれらをヒットすると本当に混乱することができるいくつかの微妙な含意があります。
読者セットが閉じられるまで、次の操作を延期することができます。この場合、これは単に不必要Open()
とClose()
取り出すことによりマイナー省のようになります。
今
using(myReader = cmd.ExecuteReader())
{
while(myReader.Read())
{
string info = myReader.GetString("info");
/* Do stuff */
using(SqlConnection logConn = new SqlConnection(...))
{
logConn.Open();
string queryLog = "INSERT INTO ....;
MySqlCommand cmdLog = new MySqlCommand(queryLog, connection);
cmdLog.ExecuteNonQuery();
}
}
}
を、2つの接続ではなく、ここでは1を持っている無駄に見えるかもしれません。ただし:
- プールすると接続がかなり安くなります。
ExecuteNonQuery()
を実行するとすぐにプールに戻しますので、多くのスレッドでこのようなことが起こっていると、外出先での接続の総数は2倍になりますスレッド。一方、これを実行するスレッドが1つしかない場合は、余分な接続が1つしかないので、誰が気にします。
- datareaderを提供する途中で接続を終了すると、プールに戻る前に余分なクリーンアップが行われている可能性があります。したがって、2つの接続を使用している可能性があります(SQLServer、そのような場合にプールに戻る前に、より多くの作業が必要なデータベースもあることはわかっています)。
要約すると、再利用せずに接続を使用することはできません。それは出てくるバグです。通常は、一度に同じ接続で複数の操作を行うことはできません。 SQLServer2005でMultipleActiveResultSets
オプションを使用すると、複雑になりますが、これを行うことができます。一般に、一度に複数のDBを処理する場合は、複数の接続を使用する必要があります。
あなたはまだif
ISNいくつかの時間が戻ってくるif
ではなくwhile
を使用しますが、それを行うことが一度に理にかなっているものだから、というよりも、あなたがそれを理解していないバグを修正することができ、言ったすべてのオプションです。
「爆発」とはどういう意味ですか? – SLaks
あなたが持っているのと同じように避けるのではなく、おそらく理解すべき根本的な問題があるようです。爆発は何を意味しますか?例外がスローされますか?どのような例外ですか? –
例外です - 私は今すぐ手元にありませんが、接続についてです。私はそれについていくつかのコードを追加するために投稿を編集しました。 – Kani