SqlCommandがタイムアウトした時にスローされるSqlExceptionを確認する

SqlCommandにはタイムアウトの時間を設定するSqlCommand.CommandTimeoutプロパティがあります。

SqlCommand.CommandTimeout プロパティ (System.Data.SqlClient)

MSDNからもわかりますがタイムアウトした時にはSqlExceptionがスローされます。

このSqlExceptionからタイムアウトの発生を確認できるのかなと思ったのでサンプルコードを書いてみました。(といいつMSDNのサンプルコードとほとんど同じですが。)

var connectionString = new SqlConnectionStringBuilder {
    DataSource = ".",
    IntegratedSecurity = true,
}.ToString();

using (var connection = new SqlConnection(connectionString)) {
    connection.Open();

    // 5秒待機するクエリ
    var query = @"waitfor delay '00:00:05';";
    using (var command = new SqlCommand(query, connection)) {
        // タイムアウトを1秒に設定
        command.CommandTimeout = 1;

        try {
            command.ExecuteNonQuery();
        } catch (SqlException exception) {
            // タイムアウトするとSqlExceptionがスロー
            Console.WriteLine("SqlException:");
            Console.WriteLine("Number: {0}, Message: {1}",
                exception.Number, exception.Message);
            Console.WriteLine("SqlErrors:");
            foreach (var error in exception.Errors.Cast<SqlError>()) {
                Console.WriteLine("Number: {0}, Message: {1}",
                    error.Number, error.Message);
            }
        }
    }
}

実行すると次のようになります。

SqlException:
Number: -2, Message: Timeout に達しました。操作が完了する前にタイムアウト期間が過ぎたか、またはサーバーが応答していません。
SqlErrors:
Number: -2, Message: Timeout に達しました。操作が完了する前にタイムアウト期間が過ぎたか、またはサーバーが応答していません。

タイムアウトの場合、SqlException.Numberは「-2」になります。SqlException.NumberはSqlException.Errosから取得される1つ目のSqlError.Numberを指しています。「-2」はついてこのあたりにも説明があります。

このプロパティの値からタイムアウトしたということが判断できますね。

おまけ

サンプルコードで使っているクエリのwaitforは一定時間待機するものです。こういうテストするときに便利な子です。

WAITFOR (Transact-SQL)