The following code give the following error when I tried to nest sql queries.
There is already an open DataReader associated with this Command which must be closed first
reader4 = cmd4.ExecuteReader()
Stack trace:
[InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.]
System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) +5333807
System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command) +51
System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async) +155
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite) +82
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +53
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +137
System.Data.SqlClient.SqlCommand.ExecuteReader() +99
CW_Recruiter_postjob.btnPostJob_Click(Object sender, EventArgs e) in C:\Users\Khav\Documents\Visual Studio 2013\WebSites\BSE14BFT_140928\CW\Recruiter\postjob.aspx.vb:42
System.EventHandler.Invoke(Object sender, EventArgs e) +0
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +9628722
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +103
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +35
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1724
Code :
Protected Sub btnPostJob_Click(sender As Object, e As EventArgs) Handles btnPostJob.Click
Dim con As New SqlConnection(ConfigurationManager.ConnectionStrings("JPortalCS").ConnectionString)
con.Open()
Dim cmd As New SqlCommand("INSERT INTO [JobDetails].[Job](Job_Title,Job_Desc,Start_Date,End_Date,Status,Category_ID,Recruiter_ID) VALUES (@Title,@Desc,@Start,@End,@Status,@Category_ID,@Recruiter_ID)", con)
cmd.Parameters.AddWithValue("@Title", job_title.Text)
cmd.Parameters.AddWithValue("@Desc", job_desc.Text)
cmd.Parameters.AddWithValue("@Start", DateTime.Now.ToString("d"))
cmd.Parameters.AddWithValue("@End", DateTime.Now.ToString("d"))
cmd.Parameters.AddWithValue("@Status", "Available")
'getting category_id
Dim reader As SqlDataReader
Dim cmd2 As New SqlCommand("SELECT * FROM [JobDetails].[Category] where Category_Desc=@cat", con)
cmd2.Parameters.AddWithValue("@cat", ddlCategory.SelectedValue)
reader = cmd2.ExecuteReader()
Dim catid As Integer
If reader.HasRows Then
reader.Read()
catid = reader.Item("Category_ID")
End If
'end
'getting user_id
Dim reader4 As SqlDataReader
Dim cmd4 As New SqlCommand("SELECT * FROM [UserDetails].[User] where User_Name=@username", con)
cmd4.Parameters.AddWithValue("@username", Session("login_user"))
reader4 = cmd4.ExecuteReader()
Dim userid As Integer
If reader4.HasRows Then
reader4.Read()
userid = reader4.Item("User_ID")
End If
'getting recruiter_id
Dim reader3 As SqlDataReader
Dim cmd3 As New SqlCommand("SELECT * FROM [UserDetails].[Recruiter] where User_ID=@user", con)
cmd3.Parameters.AddWithValue("@user", userid)
reader3 = cmd3.ExecuteReader()
Dim recruterid As String = ""
If reader3.HasRows Then
reader3.Read()
recruterid = reader3.Item("Recruiter_ID")
End If
'end
cmd.Parameters.AddWithValue("@Category_ID", catid)
cmd.Parameters.AddWithValue("@Recruiter_ID", recruterid)
cmd.CommandType = CommandType.Text
cmd.ExecuteNonQuery()
con.Close()
End Sub
the error message is self explanatory: only one data reader can be active on a single connection (see remarks in the documentation ).
you could hunt for the culprit trying to understand which of the many object that are not disposed is to blame or rewrite your code in a more clean (and readable, and elegant) way.
here follows an example of what your code should look like:
Dim catid As Integer
Dim userid As Integer
'getting category_id
Using cmd As New SqlCommand("SELECT * FROM [JobDetails].[Category] where Category_Desc=@cat", con)
cmd.Parameters.AddWithValue("@cat", ddlCategory.SelectedValue)
Using reader As SqlDataReader = cmd.ExecuteReader()
If reader.HasRows Then
reader.Read()
catid = reader.Item("Category_ID")
End If
End Using
End Using
'end
'getting user_id
Using cmd As New SqlCommand("SELECT * FROM [UserDetails].[User] where User_Name=@username", con)
cmd.Parameters.AddWithValue("@username", Session("login_user"))
Using reader As SqlDataReader = cmd.ExecuteReader()
If reader.HasRows Then
reader.Read()
userid = reader4.Item("User_ID")
End If
End Using
End Using
this way you avoid the issue because the SqlDataReader
object is disposed immediately after use and is not around to crash the next call.
another change that could improve the overall readability and stability is the use of explicit naming of fields in sql query:
SqlCommand("SELECT * FROM [JobDetails].[Category] where Category_Desc=@cat", con)
can be written as:
SqlCommand("SELECT Category_ID FROM [JobDetails].[Category] where Category_Desc=@cat", con)
there is no need to retrieve the whole row if you use just a single value.
using the above solution you could even rewrite the call to retrieve the Category_ID
field as:
'getting category_id
Using cmd As New SqlCommand("SELECT Category_ID FROM [JobDetails].[Category] where Category_Desc=@cat", con)
cmd.Parameters.AddWithValue("@cat", ddlCategory.SelectedValue)
catid = cmd.ExecuteScalar()
End Using
'end
have a look at the documentation for the behaviour and limits of ExecuteScalar
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.