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

编辑

ExecuteReader with CommanBehavior(读取数据后自动关闭连接)

要解决连接关闭问题,只需使用 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 回答