The DataReader associated with this command is already open and must be closed first. Understanding of this exception

  • 2020-05-16 06:48:45
  • OfStack

Let me begin by stating the following:
1, maybe the explanation is a little elementary, hope the master do not "spray" me, because I know not every one is a master, I am also afraid of the master said I pack 13;
2, if there is anything wrong, we also hope to point out, 1 ding modest learning;
3, this article belongs to the author of the original, respect others work, please indicate the author, thank you.
Let's move on:
Began when encounter this problem I also check a lot of information on the Internet, seemingly didn't find any good solution, then I start debugging the program, I found that sometimes run is not an error, sometimes run error, this struggle, but later I found that I put ASP NET Development Server - port xxx exit, and then run the program is not an error... I thought it was ok, but later I found a problem. As long as the port is not closed or the page is constantly refreshed when the program is running, an error will be reported: "the DataReader associated with this command has been opened, it must be closed first."
I got angry. I started debugging the program with N breakpoints and step 1. I didn't realize that I was using DataReader objects. I was speechless. After repeated deliberation, I finally found a solution. It turns out that this exception must have something to do with DataReader, or it may have something to do with Connection objects.
See the following code:
 
private static SqlConnection Sqlconnection; 
public static SqlConnection SqlConnection 
{ 
get 
{ 
string SqlconnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["TandyTang"].ToString(); 
if (Sqlconnection == null) 
{ 
Sqlconnection = new SqlConnection(SqlconnectionString); 
Sqlconnection.Open(); 
} 
else if (Sqlconnection.State == System.Data.ConnectionState.Closed) 
{ 
Sqlconnection.Open(); 
} 
else if (Sqlconnection.State == System.Data.ConnectionState.Broken) 
{ 
Sqlconnection.Close(); 
Sqlconnection.Open(); 
} 
return Sqlconnection; 
} 
} 
///<summary> 
/// SqlGetDataTable 
///<param name="proc"></param> 
///<param name="type"></param> 
///<param name="param"></param> 
///<param name="count"></param> 
///<returns>DataTable</returns> 
public static DataTable SqlGetDataTable(string proc, CommandType type, string[] param, out int count) 
{ 
DataSet ds = new DataSet(); 
using (SqlCommand cmd = new SqlCommand(proc, SqlConnection)) 
{ 
SqlParameter[] myParms = new SqlParameter[2]; 
myParms[0] = new SqlParameter("@Id", SqlDbType.Int, 4); 
myParms[0].Value = paramValue[0]; 
myParms[1] = new SqlParameter("@Name", SqlDbType.VarChar, 50); 
myParms[1].Value = paramValue[1]; 
foreach (SqlParameter parameter in myParms) 
{ 
cmd.Parameters.Add(parameter); 
} 
cmd.CommandType = type; 
SqlDataAdapter da = new SqlDataAdapter(cmd); 
da.Fill(ds); 
} 
return ds.Tables[0]; 
} 

The above code, I believe in 1 people, should be all right, I also think there is no problem. The first code is to create a data connection and open the database connection, and the second code is to create an SqlCommand, where SqlConnection is used as the first parameter, which is the crux of the problem.
If you run the SqlGetDataTable() method once on the page, you won't have any problems, and if you keep refreshing the page, you will "have an DataReader open associated with this command and must close it first." This kind of exception (probably won't appear, you try to know. The red part of the code is where the error occurs.)
After thinking, I finally found the solution. The solution is as follows. See the following code:
 
private static string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["TandyTang"].ConnectionString; 
    ///<summary> 
/// SqlGetDataTable 
///<param name="proc"></param> 
///<param name="type"></param> 
///<param name="param"></param> 
///<param name="count"></param> 
///<returns>DataTable</returns> 
public static DataTable SqlGetDataTable(string proc, CommandType type, string[] param, out int count) 
{ 
DataSet ds = new DataSet(); 
using (SqlConnection con = new SqlConnection(connectionString)) 
{ 
using (SqlCommand cmd = new SqlCommand(proc, con)) 
{ 
SqlParameter[] myParms = new SqlParameter[11]; 
myParms[0] = new SqlParameter("@Id", SqlDbType.Int, 4); 
myParms[0].Value = paramValue[0]; 
myParms[1] = new SqlParameter("@Name", SqlDbType.VarChar, 50); 
myParms[1].Value = paramValue[1]; 
foreach (SqlParameter parameter in myParms) 
{ 
cmd.Parameters.Add(parameter); 
} 
cmd.CommandType = type; 
using (SqlDataAdapter da = new SqlDataAdapter(cmd)) 
{ 
da.Fill(ds); 
} 
} 
return ds.Tables[0]; 
} 
} 

Notice the difference. Instead of using the SqlConnection method, the above method writes the SqlConnection object into using(){}.
PS: I personally suggest that you do not use the first method, you may encounter a lot of trouble oh, personal advice to use using(){} statement to ADO.NET no object in using(){} inside the best, using(){} benefits I think we all know, so I do not do too much to explain.

Related articles: