0

クエリを実行して SqlDataReader を返す関数を作成しましたが、返されたデータを処理する別の関数でそれを使用していますが、リーダーが既に閉じられているというエラーが表示されます。ここに関数があります:

public static SqlDataReader ExecuteReader(string procedure, SqlParameter[] parameters, CommandType commandType)
    {
        SqlDataReader reader = null;
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            using (SqlCommand command = new SqlCommand(procedure, connection))
            {
                connection.Open();
                if(parameters != null)
                {
                    if (commandType == CommandType.StoredProcedure)
                        command.Parameters.AddRange(parameters);
                }
                reader = command.ExecuteReader();
            }
        }
        return reader;
    }

ここに私がSqlDataReaderを呼び出しているコードがあります

using (SqlDataReader reader = SqlHelper.ExecuteReader("select top 10 username from users", null, System.Data.CommandType.Text))
        {
            Response.Write(reader.IsClosed); //This returns True

        }
4

4 に答える 4

2

編集

CommanBehavior を使用した ExecuteReader (データの読み取り後に自動的に接続を閉じる)

接続を閉じる問題を解決するには、CommandBheviour を利用するだけです

- CommandBehavior.CloseConnection 
   When you pass above values as argument to ExecuteReader 
     1. there is no need to close connection explicitly connection get close when you close your reader. 

コードはこのようになり、明示的に接続を閉じる必要はありません

public void CreateMySqlDataReader(string mySelectQuery,string myConnectionString) 
{
   SqlConnection myConnection = new SqlConnection(myConnectionString);
   SqlCommand myCommand = new SqlCommand(mySelectQuery, myConnection);
   myConnection.Open();
   SqlDataReader myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
   while(myReader.Read()) 
   {
      Console.WriteLine(myReader.GetString(0));
   }
   myReader.Close();
   //Implicitly closes the connection because CommandBehavior.CloseConnection was specified.
}

接続を閉じているため、問題が発生しています

SqlReader は常にオープン接続を使用します。つまり、これを使用するときに開いているライブ接続です。

using (SqlConnection connection = new SqlConnection(connectionString)) 
        {
}

リーダーオブジェクトによって使用される接続オブジェクトを破棄するため、IsColosed を true として返す理由

切断されたデータオブジェクトである DataTable を使用するよりもオブジェクトを返したい場合は、接続を使用します

変更されたコード

  public static DataTable ExecuteReader(string procedure, SqlParameter[] parameters, CommandType commandType)
  {
     DataTable dt = null;
     using (SqlConnection connection = new SqlConnection(connectionString))
     {
         using (SqlCommand command = new SqlCommand(procedure, connection))
         {
              connection.Open();
              if(parameters != null)
              {
            if (commandType == CommandType.StoredProcedure)
            command.Parameters.AddRange(parameters);
              }
                SqlDataAdapter da = new SqlDataAdapter(command);
                da.Fill(dt);
           }
         }
            return dt;
        }
于 2012-08-21T19:05:52.780 に答える
1

DataReader にはオープン接続が必要です。できることは、DataTable を返すか、カスタム クラスを使用して SQL クエリの結果を表し、そのインスタンスを返すことです。

エンティティを表すクラスを作成します

public class Customer
{
  public int ID { set;get;}
  public string Name { set;get;}
}

そしてあなたの方法の中で;

public List<Customer> GetCustomer()
{
  List<Customer> custList=new List<Customer>();
  using (SqlConnection connection = new SqlConnection(connectionString))
  {
    using (SqlCommand command = new SqlCommand("yourParameterizedSQLQuery", 
                                                                  connection))
    {
     //Add parameters if needed
     connection.Open();

    using (var reader = cmd.ExecuteReader())
    {
       if (reader.HasRows)
       {
           cust=new Customer();
           while(reader.Read())
           {
             var cust=new Customer();
             // TO DO :Do db null checking before reading 
             cust.ID=reader.GetInt32(reader.GetOrdinal("ID"));
             cust.Name=reader.GetString(reader.GetOrdinal("Name"));
             custList.Add(cust);
           }
       }
     }
    }
  }  
 return custList;   
 }   
于 2012-08-21T19:19:22.617 に答える
0

問題はusing SqlConnection、スコープを離れるときにデータベースへの接続を閉じることです。

SqlDataReader「まだ開いている」接続が必要です。それを親に戻しても、接続を開いたままにすることはできません。

DataSetあなたの選択は、基本的に、「接続されていない」データソースであるを返すか、接続を管理する方法を変更して、 を使用しSqlDataReader、接続を閉じることです。

于 2012-08-21T19:09:07.003 に答える
0

接続を開いたままにし、呼び出し元のコードでリーダーに関連付けられた接続を閉じる必要がある場合があります。

この課題があったので、戻り値のタイプをに変更しますDataTable

reader = command.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);
return dt;

そうすれば、そのメソッドの外で接続を閉じることを心配する必要はありません

于 2012-08-21T19:12:39.943 に答える