読者です 読者をやめる 読者になる 読者になる

checkpoint

自分用のIT技術系ノートです。古い情報や間違っている情報もあるので注意。

ADO.NET経由でSQLがデッドロックになった場合、SqlCommand.ExecuteReaderメソッドがエラーにならないことがある件

.NET SQL Server

やばい、これ今日初めて知ったんだけど。

というか、このせいで半日くらい潰されました。

MSDNにもしっかり書いてありますね。引用。

トランザクションデッドロック状態になると、 Read が呼び出されるまで、例外はスローされない可能性があります。

Framework2.0の資料にはこの記述は無くて、3.0〜4.0にはきっちり書かれています。

今日起こったのは1.1の環境だったので、きっと2.0でも起こり得る現象なんでしょう。

これの何が困るって、実際のコードでは

using(SqlDataReader myReader = myCommand.ExecuteReader()) // ← ここでエラーにならず
{
   if(!myReader.HasRows) // ← ここでもエラーにならず、HasRowsはfalse
   {
      while(myReader.Read()) // ← ここでエラーになるはずだが、到達しない
      {
         (略)
      }
   }
}

みたいにHasRowsプロパティで判断させている箇所が多いこと!

「目に見えるバグはいいバグだ。本当に恐ろしいのは何年も誰も気付かず、ごくまれにおかしな結果を返すバグだ。」

ってじっちゃも言ってた。

ちなみに、ちゃんとExecuteReaderでエラーになるケースもあるので(この辺が謎)、再現も難しいと思われ。

「再現しにくく、見つけにくく、しかし結構致命的。」という凶悪なバグになり得ますよ、これ。

今度からHasRowsは使わず、すぐにReadするようにしましょう。