2016-11-08 6 views
1

この質問に重複して記載する前に、わかりにくい難しい部分をここに示します。このエラーは散発的ですが、コードは正しいと思っていますし、いつも動作していて、リーダー部分のif else条件で起こりうるミスを処理しています。ここでは、コードは次のとおりです。コードが同期されていませんthrowingインデックスが範囲外でしたか?

public static Tuple<int, string> GetIDAndString(string term) 
{ 
    try 
    { 
     using (SqlConnection con = GetConnection()) 
     using (cmd = new SqlCommand()) 
     using (myReader) 
     { 
      int ID = 0; 
      string status = string.Empty; 
      cmd.Connection = con; 
      con.Open(); 
      cmd.CommandText = @"SELECT t.TableID, t.Status 
           FROM Table t WITH (NOLOCK) /* I know NOLOCK is not causing the mistake as far as I know */ 
           WHERE t.Term = @term"; 
      cmd.Parameters.AddWithValue("@term", term); 

      myReader = cmd.ExecuteReader(); 
      while(myReader.Read()) 
      { 
       ID = myReader.IsDBNull(0) ? 0 : myReader.GetInt32(0); 
       status = myReader.IsDBNull(1) ? string.Empty : myReader.GetString(1).Trim(); 
      } 

      myReader.Close(); 

      return new Tuple<int, string>(ID, status); 
     } 
    } 
    catch (Exception) 
    { 
     throw; 
    } 
} 

私はタプルの代わりにクラスを使用する必要があります知っているが、私は、既存のコードを変更し、あなたが見ることができるようにすることはできません。したがって、主な問題は、プロダクションサーバーにはその方法にIndex out of bounds array exceptionがあったが、問題の原因を特定できないということです。

クエリにキーワードが見つからない場合でも、myReaderは入力されず、ID = 0、status = string.Emptyが返されます。コードをデバッグして、develpment serverで作業しているときに、コードがどこからでもクラッシュするようになり、テストされたコードがどこにあるのかの例外が表示され、その解決策を再開する必要があります溶液を洗浄する)。

だから、私は誰かがそのようなことを経験していることを、production serverで願っています。私はプロダクションサーバの仕様を持っていないので、サーバについて何も知らない。

+0

新しいデータリーダーを作成して共有しないでください!これはあなたに問題をもたらす可能性があります! – mybirthname

+0

前のコメントに同意するか、新しいインスタンスを作成するか、または新しいインスタンスを作成するか、そのインスタンスへのアクセスを同期します。 –

+0

@mybirthname、私はプログラミングが初めてです。あなたはdataReaderを共有しないと言っています。あなたは、保護された静的なSqlDataReaderを宣言したクラスを使用せずに、それをusingブロックで使用することを意味しますか? –

答えて

1

最初にtry/catchブロックは必要ありません。何もしません。その後、クラス内でSqlDataReaderを共有しないと、これは問題を引き起こす可能性があり、おそらくこの問題が原因です。あなたはあなたの中でいつもIDStatusの値を上書きしています。あなたの質問にTop 1と連絡し、正しいフィールドで注文することをお勧めします。また、Dispose()SqlCommand、コンストラクタSqlCommandSupressFinalization()と呼び出す必要はありません。

なぜこの問題が発生する可能性がありますか:クエリがTableIDStatus列の1000レコードを返し、whileループに入っているとします。この瞬間、他のユーザーがアプリケーションに入り、別のメソッドを実行してSqlDataReaderを上書きし、1つの列で5つのレコードを返します。あなたがループしている間、あなたの次の反復で例外を受け取ります。そのため、クラス全体で読者をstaticと決して定義するべきではありません。静的変数は、すべてのアプリケーションユーザー間で共有されます。

public static Tuple<int, string> GetIDAndString(string term) 
{ 
    int ID = 0; 
    string status = string.Empty; 

    using (SqlConnection con = GetConnection()) 
    { 
     SqlCommand cmd = new SqlCommand(); 
     cmd.Connection = con; 
     con.Open(); 

     cmd.CommandText = @"SELECT t.TableID, t.Status 
          FROM Table t WITH (NOLOCK) /* I know NOLOCK is not causing the mistake as far as I know */ 
          WHERE t.Term = @term"; 
     cmd.Parameters.AddWithValue("@term", term); 


     using(SqlDataReader myReader = cmd.ExecuteReader()) 
     { 
      while(myReader.Read()) 
      { 
       ID = myReader.IsDBNull(0) ? 0 : myReader.GetInt32(0); 
       status = myReader.IsDBNull(1) ? string.Empty : myReader.GetString(1).Trim(); 
      } 

     } 

    } 

    return new Tuple<int, string>(ID, status); 
} 
+0

すばらしい説明!私はあなたに正解を与えるでしょう。なぜなら、それは他のものと同じですが、私のコードがベストプラクティスの例であるからです。他のものだけがあなたが私のためにそれを明確にすることを願っています。 'GetConnection()'メソッドで 'protected static SqlTransaction'を使用している場合は、クラス内のSqlReaderのように変更する必要がありますか?それともSqlReaderだけ?ありがとう –

+0

@ JorgeFはい静的なトランザクションを使用しないでください。 msdnの記事を確認してください:https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction(v=vs.110).aspx。 – mybirthname

+0

ありがとう、私はこれらの変更を行うつもりだ –

0

結果セットが期待通りではないため、ID = myReader.IsDBNull(0) ? 0 : myReader.GetInt32(0);またはstatus = myReader.IsDBNull(1) ? string.Empty : myReader.GetString(1).Trim();を入力すると、これが発生する可能性があります。実際に読む前に読者の行のログを追加すると、問題を特定するのに役立ちます。

0

私はこの問題が静的であると思われるmyReaderフィールドに起因すると推測します。 SqlDataReader(フィールドの型であると仮定)ドキュメントhttps://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader(v=vs.110).aspxを見ると、インスタンスメソッドはスレッドセーフではないことがわかります。そのため、そのフィールドへのアクセスを同期させる必要があります。

0

using (myReader)は、読者がその時に持っていた値を取得し、後でそれを廃棄します。変数を覚えていません。これは、この例からわかるように、using (Random() ? myReader : null)でなければなりません。明らかに、C#言語は処理時間にその式を再実行しません。それは一度だけ実行されます。

古い/他の読者を処分しています。

スレッド間でオブジェクトを共有している場合(静的変数を使用している可能性があります)、これはほとんど競合状態です。それをしないでください。地元の人を使用してください。静的変数を使用する必要はありません。

関連する問題