。ネット:SqlDataReader.Close または .Dispose の結果、タイムアウト期限切れ例外が発生します
-
02-07-2019 - |
質問
SqlDataReader で Close または Dispose を呼び出そうとすると、タイムアウト期限切れの例外が発生します。SQL Server への DbConnection がある場合は、次のようにして自分で再現できます。
String CRLF = "\r\n";
String sql =
"SELECT * " + CRLF +
"FROM (" + CRLF +
" SELECT (a.Number * 256) + b.Number AS Number" + CRLF +
" FROM master..spt_values a," + CRLF +
" master..spt_values b" + CRLF +
" WHERE a.Type = 'p'" + CRLF +
" AND b.Type = 'p') Numbers1" + CRLF +
" FULL OUTER JOIN (" + CRLF +
" SELECT (print("code sample");a.Number * 256) + b.Number AS Number" + CRLF +
" FROM master..spt_values a," + CRLF +
" master..spt_values b" + CRLF +
" WHERE a.Type = 'p'" + CRLF +
" AND b.Type = 'p') Numbers2" + CRLF +
" ON 1=1";
DbCommand cmd = connection.CreateCommand();
cmd.CommandText = sql;
DbDataReader rdr = cmd.ExecuteReader();
rdr.Close();
Reader.Close() または Reader.Dispose() を呼び出すと、System.Data.SqlClient.SqlException がスローされます。
- エラーコード:-2146232060 (0x80131904)
- メッセージ:「タイムアウトになりました。操作が完了する前にタイムアウト時間が経過したか、サーバーが応答していません。」
解決
これは、データ リーダーを開いたばかりで、まだ完全に反復処理を行っていないためです。まだ完了していないデータ リーダー (DbConnection も) を閉じる前に、DbCommand オブジェクトを .Cancel() する必要があります。もちろん、DbCommand を .Cancel() することによって、これについてはわかりませんが、他の例外が発生する可能性があります。しかし、それが起こったら捕まえるべきです。
他のヒント
クルーザーは次のような答えを出しました。command.Cancel() を呼び出します:
using (DbCommand cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
using (DbDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
if (WeShouldCancelTheOperation())
{
cmd.Cancel();
break;
}
}
}
}
また、リーダーがすでにすべての行を読み取っている場合でも、Cancel を呼び出すことができることを知っておくと役立ちます (つまり、一部は投げません 「キャンセルするものはありません」 例外。)
DbCommand cmd = connection.CreateCommand();
try
{
cmd.CommandText = sql;
DbDataReader rdr = cmd.ExecuteReader();
try
{
while (rdr.Read())
{
if (WeShouldCancelTheOperation())
break;
}
cmd.Cancel();
}
finally
{
rdr.Dispose();
}
}
finally
{
cmd.Dispose();
}
実際にデータをどこで読み取るのでしょうか?リーダーを作成しているだけで、データを読み取っているわけではありません。これは単なる推測ですが、読んでいない場合は読者が閉じるのに問題があるかもしれません ;)
DbDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
{
int index = rdr.GetInt32(0);
}
所属していません StackOverflow