Invalid attempt to Read when reader is closed

Howlleo

Member
Joined
Jan 14, 2008
Messages
13
Programming Experience
Beginner
Hope it's OK to continue this here.
Project is nearly done, and that's good, because it's due tomorrow.


This code is for a student registration form. Student chooses classes using a dropdown. Code then
1. assigns classes and their sectionID to an array, finds their credit value, assigns that to the array.
2. Checks that the student hasn't registered for more than 18 credits
3. Checks that all the necessary prerequisites have been taken
4. Checks that the student hasn't tried to register for the same class twice
5. Writes the selected classes back into the database

Parts 1-4 work perfectly as long as Part 5 is not included. Meaning, when I comment out the subroutine that writes, everything goes smoothly.

As soon as I add in the subroutine that writes to the database, I have trouble with the subroutine that checks for prerequisites.

Meaning, as soon as I add Sub WriteClasses() to the end of Sub NoDouble() I begin having errors with Sub CheckPrereq().

Code and Error below and attached in a word doc.

I know it's a lot of code, but please help me!

VB.NET:
<script runat="server">

    Protected Sub RegisterButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim CreditsArray(12, 2) As Object
        ' call subroutine to assign each selected class and its code to a 2-dimensional array
        AssignArray(CreditsArray)
        '' call subroutine to find the credits awarded for each class
        GetCreditValue(CreditsArray)
        ' Call function to total the credits registered and return the value
        Dim TotalCredits As Integer
        TotalCredits = CreditTotal(CreditsArray)
        ' Check to see if there are too many credits
        ' Disallow registration if there is an overload
        If TotalCredits > 18 Then
            Response.Write("You have registered for more than 18 credits. Please remove classes until you are registering for 18 or fewer classes. Contact an advisor for futher assistance.")
            Exit Sub
        Else
            Response.Write("<br/>You have not registered for too many credits.<br/>")
            'call a subroutine to check for prerequisites
            CheckPrereq(CreditsArray)
            ' If prereqs in order, the subroutine calls Sub WriteClasses to write them to the database
        End If
    End Sub
    
   
    'Subroutine AssignArray assigns the values from the DropDownLists and Labels to an array
    Sub AssignArray(ByVal CreditsArray)
        
        CreditsArray(0, 0) = DropDownList1.SelectedItem.Value
        CreditsArray(0, 2) = Label1.Text
        CreditsArray(1, 0) = DropDownList2.SelectedItem.Value
        CreditsArray(1, 2) = Label2.Text
        CreditsArray(2, 0) = DropDownList3.SelectedItem.Value
        CreditsArray(2, 2) = label3.Text
        CreditsArray(3, 0) = DropDownList4.SelectedItem.Value
        CreditsArray(3, 2) = Label4.Text
        CreditsArray(4, 0) = DropDownList5.SelectedItem.Value
        CreditsArray(4, 2) = Label5.Text
        CreditsArray(5, 0) = DropDownList6.SelectedItem.Value
        CreditsArray(5, 2) = Label6.Text
        CreditsArray(6, 0) = DropDownList7.SelectedItem.Value
        CreditsArray(6, 2) = Label7.Text
        CreditsArray(7, 0) = DropDownList8.SelectedItem.Value
        CreditsArray(7, 2) = Label8.Text
        CreditsArray(8, 0) = DropDownList9.SelectedItem.Value
        CreditsArray(8, 2) = Label9.Text
        CreditsArray(9, 0) = DropDownList10.SelectedItem.Value
        CreditsArray(9, 2) = Label10.Text
        CreditsArray(10, 0) = DropDownList11.SelectedItem.Value
        CreditsArray(10, 2) = Label10.Text
        CreditsArray(11, 0) = DropDownList12.SelectedItem.Value
        CreditsArray(11, 2) = Label12.Text
        CreditsArray(12, 0) = DropDownList13.SelectedItem.Value
        CreditsArray(12, 2) = Label13.Text
    End Sub
    
    'GetCreditValue returns the number of credits being awarded for each class to the second column in the array
    Sub GetCreditValue(ByVal CreditsArray)
        Dim i As Integer
        For i = 0 To 12
                           
            Dim ClassDb As SqlConnection
            Dim cmdSelectClass As SqlCommand
            Dim dtrClass As SqlDataReader
        
            ClassDb = New SqlConnection("Server=LONNA\SQLEXPRESS;Integrated Security=True;database=LGordonTouroReg")
            cmdSelectClass = New SqlCommand("SELECT Credits FROM Class WHERE ClassID=@ClassID", ClassDb)
            cmdSelectClass.Parameters.AddWithValue("@ClassID", CreditsArray(i, 0))
            ClassDb.Open()
            dtrClass = cmdSelectClass.ExecuteReader()
            While (dtrClass.Read())
                CreditsArray(i, 1) = dtrClass(0)
            End While
            dtrClass.Close()
            ClassDb.Close()
            Response.Write("The value for " & CreditsArray(i, 0) & " is " & CreditsArray(i, 1) & "<br/>")
        Next i
    End Sub
    
    
    
    ' function CreditTotal adds up the number of credits being registered for and returns the total
    Function CreditTotal(ByVal CreditsArray(,)) As Integer
        Dim TotalCredits As Integer = 0
        For j As Integer = 0 To 12
            TotalCredits = TotalCredits + CreditsArray(j, 1)
        Next j
        Return TotalCredits
    End Function
    
    
    
    ' Subroutine that checks database for prerequisites to the classes and if the student has them
    Sub CheckPrereq(ByVal creditsArray)
        Dim i As Integer
        For i = 0 To 12
                           
            Dim PrereqDb As SqlConnection
            Dim cmdFindPrereq As SqlCommand
            Dim dtrPrereq As SqlDataReader
            Dim Prerequisite As String
        
            PrereqDb = New SqlConnection("Server=LONNA\SQLEXPRESS;Integrated Security=True;database=LGordonTouroReg")
            cmdFindPrereq = New SqlCommand("SELECT Prerequisites FROM Class WHERE ClassID=@ClassID", PrereqDb)
            cmdFindPrereq.Parameters.AddWithValue("@ClassID", creditsArray(i, 0))
            'Open SqlConnection
            PrereqDb.Open()
            'Execute the command
            dtrPrereq = cmdFindPrereq.ExecuteReader()
         
            While (dtrPrereq.Read())
                If dtrPrereq.HasRows Then
                    Prerequisite = dtrPrereq(0)
                    If Not Prerequisite = "none" Then
                        Response.Write("The class " & creditsArray(i, 0) & " has the prerequisite " & Prerequisite & ". <br/> ")
                        Dim ClassHistoryDb As SqlConnection
                        Dim cmdFindClassHistory As SqlCommand
                        Dim dtrClassHistory As SqlDataReader
                        ClassHistoryDb = New SqlConnection("Server=LONNA\SQLEXPRESS;Integrated Security=True;database=LGordonTouroReg")
                        cmdFindClassHistory = New SqlCommand("Select * FROM Enrollment WHERE (StudentID=@StudentID) AND (ClassID = @ClassID)", ClassHistoryDb)
                        cmdFindClassHistory.Parameters.AddWithValue("@StudentID", Profile.StudentID)
                        cmdFindClassHistory.Parameters.AddWithValue("@ClassID", Prerequisite)
                        ClassHistoryDb.Open()
                        dtrClassHistory = cmdFindClassHistory.ExecuteReader()
                        If Not dtrClassHistory.HasRows Then
                            Response.Write("You do not have the prerequisite of " & Prerequisite & " required  for " & creditsArray(i, 0) & ". Remove it from your schedule and try again. <br/> ")
                            dtrPrereq.Close()
                            PrereqDb.Close()
                            dtrClassHistory.Close()
                            ClassHistoryDb.Close()
                            Exit Sub
                        Else
                            Response.Write("You have the prerequisite of " & Prerequisite & " required for " & creditsArray(i, 0) & " so go ahead and register. <br/>")
                            dtrPrereq.Close()
                            PrereqDb.Close()
                            dtrClassHistory.Close()
                            ClassHistoryDb.Close()
                        End If
                    End If
                End If
            End While
        Next i
        ' If prereqs in order, call the check for double enrollment in same semester
        NoDouble(creditsArray)
    End Sub
    
    
    'Subroutine checks if the student has attempted to enroll in a class twice and doesn't permit it.
    Sub NoDouble(ByVal CreditsArray)
        Dim i As Integer
        For i = 0 To 12
            If Not CreditsArray(i, 0) = "" Then
                For j As Integer = i + 1 To 12
                    If CreditsArray(i, 0) = CreditsArray(j, 0) Then
                        Response.Write("You cannot enroll for the same class twice. <br/>")
                        Response.Write("You have selected " & CreditsArray(i, 0) & " twice. <br/>")
                        Exit Sub
                    End If
                Next j
            End If
        Next i
        Response.Write("You have not tried to register for anything twice.")
        'call the sub to write the data to the enrollment table
        WriteClasses(CreditsArray)
    End Sub
    
     
    Sub WriteClasses(ByVal CreditsArray)
        Dim i As Integer
        Dim EnrollDb As SqlConnection
        Dim cmdEnroll As SqlCommand
        EnrollDb = New SqlConnection("Server=LONNA\SQLEXPRESS;Integrated Security=True;database=LGordonTouroReg")
        cmdEnroll = New SqlCommand("INSERT INTO Enrollment (SectionID, Semester, Year, ClassID, StudentID) VALUES ('@SectionID', 'Fall', '2007', '@ClassID', '@StudentID')", EnrollDb)
        cmdEnroll.Parameters.AddWithValue("@SectionID", CreditsArray(i, 2))
        cmdEnroll.Parameters.AddWithValue("@ClassID", CreditsArray(i, 0))
        cmdEnroll.Parameters.AddWithValue("@studentID", Profile.StudentID)
        EnrollDb.Open()
        For i = 0 To 12
            cmdEnroll.ExecuteNonQuery()
            Response.Write(CreditsArray(i, 0) & " has been added to your schedule.")
        Next i
        EnrollDb.Close()
    End Sub
    
    
</script>

ERROR MESSAGE

Invalid attempt to Read when reader is closed.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: Invalid attempt to Read when reader is closed.

Source Error:

Line 114: dtrPrereq = cmdFindPrereq.ExecuteReader()
Line 115:
Line 116: While (dtrPrereq.Read())
Line 117: If dtrPrereq.HasRows Then
Line 118: Prerequisite = dtrPrereq(0)

Source File: C:\Users\Lonna\Documents\Visual Studio 2005\WebSites\LGordonTouroReg\RegistrationPage.aspx Line: 116

Stack Trace:

[InvalidOperationException: Invalid attempt to Read when reader is closed.]
System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout) +600
System.Data.SqlClient.SqlDataReader.Read() +9
ASP.registrationpage_aspx.CheckPrereq(Object creditsArray) in C:\Users\Lonna\Documents\Visual Studio 2005\WebSites\LGordonTouroReg\RegistrationPage.aspx:116
ASP.registrationpage_aspx.RegisterButton_Click(Object sender, EventArgs e) in C:\Users\Lonna\Documents\Visual Studio 2005\WebSites\LGordonTouroReg\RegistrationPage.aspx:25
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +75
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +97
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4921
 

Attachments

  • script runat.doc
    52 KB · Views: 16
Do dtrPrereq.Close() after the While dtrPrereq.Read loop, if you need to exit the loop before reader is finished use "Exit While". Same goes for PrereqDb.Close, don't close the connection until you're finished using it.
 
Back
Top