2011-02-06 10 views
0

ここに私のコードですが、私は読者を閉じて開きます。いくつかのスレッドがこの機能に同時にアクセスできますが、ロックがあります。これは、初めに数回動作しますが、遅かれ早かれ、私が与えるもの私はこのエラーが発生し続ける: "リーダーが閉じているときに読み込みを呼び出す試みが無効です"

private IList<BursaUser> GetUsers(SqlCommand cmd) 
{ 
IList<User> users = new List<User>(); 
User user; 
lock (thisLock) 
    { 
     SqlDataReader dr = null; 

     try 
     { 
      Conn.Open(); 
      dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); 
      while (dr.Read()) 
      { 
       user = new User 
       { 
        UserId = Convert.ToInt32(dr["WorkerNum"]), 
        CompanyName = dr["CompanyName"].ToString(), 
        WorkerName = dr["WorkerFirstName"] + " " + dr["WorkerFamilyName"], 
             Phone = dr["Phone"].ToString() 
            }; 
         if (dr["QueueNum"] != null && dr["QueueNum"] != DBNull.Value) 
         { 
          user.Queue = new Queue 
          { 
            HasAlreadyEntered = 
            dr["flgAppear"] != null && dr["flgAppear"].ToString() == "Y", 
            IsFromWebsite = dr["TookFrom"].ToString() == "1", 
            IsMelutash = dr["IsMelutash"].ToString() == "1", 
            TimeOrdered = DateTime.Parse(dr["DateTime1"].ToString()), 
               QueueNum = Convert.ToInt32(dr["QueueNum"]), 
               SMS = dr["SMSCode"].ToString() 
              }; 
         } 
         users.Add(user); 
        } 
       } 
       catch (Exception e) 
       { 
        throw e; 
       } 
       finally 
       { 

        if (dr != null) 
        { 
         dr.Close(); 
         dr.Dispose(); 
        } 


       } 
       return users; 
      } 
     } 

で例外「リーダーがクローズされたときに無効な試みがリードを呼び出すために」を得ますか?

+0

[返信DataReader from DataLayer usingステートメント](http://stackoverflow.com/questions/850065/return-datareader-from-datalayer-in-using-statement) – nawfal

答えて

11

はのは、このコードを少し改善してみましょう:

private IEnumerable<BursaUser> GetUsers() 
{ 
    using (var conn = new SqlConnection(SomeConnectionString)) 
    using (var cmd = conn.CreateCommand()) 
    { 
     conn.Open(); 
     cmd.CommandText = "SELECT WorkerNum, CompanyName, ... FROM Users"; 
     using (var reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       var user = new User 
       { 
        UserId = reader.GetInt32(reader.GetOrdinal("WorkerNum")), 
        CompanyName = reader.GetString(reader.GetOrdinal("CompanyName")), 
        // TODO: complete other fields 
       }; 
       // TODO: do the tests and complete the complex properties 
       yield return user; 
      } 
     } 
    } 
} 

は今、このコードは完全にリエントラントで、スレッドセーフ。ロックは必要ありません。

+1

+1、素晴らしい答え。私は2つのことを追加します:私はいつも明示的に私のデータ・リーダーと接続を 'Close'しています。そうしないと、Dispose中に例外がスローされることがあります。 - 第二に、私はこのメソッドを怠惰にすること( 'yield return'でビルドされた' IEnumerable 'を返すこと)が良いアイデアだと思いますが、すべての状況においてそうでないかもしれません。結局、シーケンスが完全に消費されない限り、DB接続は開いたままになります。 – stakx

+0

@stakx、うーん、それは変だ。私はデータの読者を明示的に閉鎖したことは一度もなく、問題は一度もありませんでした。 –

+0

ありがとうございます、あなたが書いたものと一致するようにコードを変更しましたが、まだエラーが発生します。 – Eitan

関連する問題