2012-01-21 2 views
0

私のdatareaderが既に開いているというエラーが表示されました。DataReaderがすでに開かれています

私のコードは、DataReaderのコマンドがalreader開いていることを言ってRole.GetRoleByIDでこの

public static Users GetByID(int ID, SqlConnection connection) 
    { 
     SqlCommand command = new SqlCommand("Select Name, Email, LastLogin, FK_Role_ID from Users where [email protected]"); 
     command.Connection = connection; 

     command.Parameters.Add(new SqlParameter("id", ID)); 

     SqlDataReader reader = command.ExecuteReader(); 
     if (reader.Read()) 
     { 
      Users user = new Users(); 
      user.ID = ID; 
      user.Name = reader.GetString(0); 
      user.Email = reader.GetString(1); 
      user.LastLogin = reader.GetString(2); 
      user.role = Role.GetRoleByID(reader.GetInt32(3), connection); 
      reader.Close(); 
      return user; 
     } 
     else 
     { 
      reader.Close(); 
      return null; 
     } 
    } 

エラーoccoursのように見えます。どちらが当てはまりますか?私のリーダーからの情報でRole.GetRoleByIDを呼び出すにはどうすればいいですか? C#で

IコードとASP.NET

+0

なぜあなたのクエリにGetRoleByIDを組み込みませんか? –

答えて

4

は、それがどのように見えるあなたのRole.GetRoleByID接続を再利用しようとします。

オプション:

  • あなたはGetByIDSqlDataReaderから必要なデータを取得し、そのリーダーを閉じて、コールRole.GetRoleByID、その後は(あなたが一度に一つのアクティブなリーダーを持っている)
  • 複数のアクティブな結果セット(MARS)を有効にする - 私はその経験があるとは言いません
  • メソッド間の依存関係を減らすために、それぞれのメソッドを別々の接続にします。接続プールによって開閉がかなり安くなることに注意してください。

私があなたの場合は、最初のオプション、またはおそらく最後のオプションを指定します。私はまた、自動的に読者を閉じるためにusingステートメントを使用したい:

private const string GetUserByIdSql = 
    "Select Name, Email, LastLogin, FK_Role_ID from Users where [email protected]"; 

public static Users GetByID(int ID, SqlConnection connection) 
{ 
    var sql = ; 
    Users user; 
    int roleId; 
    using (var command = new SqlCommand(GetUserByIdSql, connection)) 
    { 
     command.Parameters.Add(new SqlParameter("id", ID)); 
     using (var reader = command.ExecuteReader()) 
     { 
      if (!reader.Read()) 
      { 
       return null; 
      } 
      user = new Users 
      { 
       Name = reader.GetString(0), 
       Email = reader.GetString(1), 
       LastLogin = reader.GetString(2), 
      }; 
      // Remember this so we can call GetRoleByID after closing the reader 
      roleID = reader.GetInt32(3); 
     } 
    } 
    user.Role = Role.GetRoleByID(roleID, connection); 
    return user; 
} 

4番目のオプションとして - なぜちょうどあなたの既存のクエリにGetRoleByIDで必要とされるジョインを実行していませんか?それはあなたがデータベースへの1回のトリップだけを必要とすることを意味します。

+0

+1 for文 – CodeZombie

+0

私のコードでは、読者が読んでいない場合、返り値nullはフォールバックです。あなたのコードでは、リターンユーザは、読者が読んでいなくても作られています。これがヌルの結果にどのように影響しますか? –

+1

@MichaelTotKorsgaard:もう一度見てください: 'if(!reader.Read()){return null; } ' –

1

MARSに接続文字列(MultipleActiveResultSets=true)を許可しましたか?

1

同じクエリからロールを受け取れるようにするには、Select join with requisite joinを使用することを検討してください。

また、(using reader = command.ExecuteReader())を使用することをお勧めします。これにより、読み取りが終了し、範囲が終了するとすぐに廃棄されるようになります。