我创建了一个函数,它执行查询并返回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
}
编辑
带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))
{
}
它处理了读取器对象使用的连接对象,这就是为什么它将IsColosse重新作为真正的
如果你想返回值的对象,而不是使用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;
}
DataReader需要一个开放连接。您可以返回DataTable或Have自定义类来表示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;
}
问题是您有using SqlConnection
,它在离开作用域时关闭与数据库的连接。
SqlDataReader
需要一个"仍然打开"的连接。将其返回给父级不会保持连接处于打开状态。
您的选择基本上是返回一个DataSet
,这是一个"未连接"的数据源,或者更改管理连接的方式以打开它,使用SqlDataReader
,关闭连接。
您可能必须保持连接打开,并让调用代码关闭与读取器关联的连接。
我遇到了这个挑战,所以我将返回类型更改为DataTable
reader = command.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);
return dt;
这样,我就不必担心关闭该方法之外的连接