连接字符串 属性。连接的当前状态

ConnectionString property. The connection's current state

这是我的登录表单的当前编码

 Option Strict On
'-------------------------------------------
' Imports required for DB Connectivity
'------------------------------------------
Imports System.Data.OleDb
Imports ShadowLogin.GlobalVariables

Public Class ShadowLogin
Dim Main As New ShadowMain

'-------------------------------------------------------------------------------------------------------------------------------
' Establish Database Connectivity parameters
'-------------------------------------------------------------------------------------------------------------------------------
Dim cnnOLEDB As New OleDbConnection
Dim cmdOLEDB As New OleDbCommand
Dim strConnectionString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Environment.CurrentDirectory & "\shadow.mdb"


'-------------------------------------------------------------------------------------------
' System Login
'-------------------------------------------------------------------------------------------
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click

    Dim selectedbutton As New RadioButton
    Dim Cancel As Boolean

    'Checks RedID is numerical digits only 
    If Not IsNumeric(txtRedID.Text) Then
        MsgBox("Please Check RedID.", vbInformation)

        'you may also consider erasing it
        txtRedID.Text = ""
        txtRedID.Focus()
        Exit Sub

        'checks that RedID is 9 characters long
    ElseIf txtRedID.Text.Length < 9 Then
        txtRedID.Focus()
        txtRedID.SelectAll()
        MsgBox("Please Check RedID", MsgBoxStyle.Exclamation)
        Exit Sub
    Else
        Cancel = True
    End If

    'Checks that a password has been entered
    If txtPassword.Text = "" Then
        MsgBox("Please Enter a Password", MsgBoxStyle.Exclamation, MsgBoxStyle.OkOnly)
        Exit Sub
    End If

    'if radiobutton is selected then continue
    If GroupBox1.SelectedRadioButton(selectedbutton) Then
        Main = New ShadowMain
        'Checks if radiobutton is selected and hides tabs 
        If optStudent.Checked = True Then
            ShadowMain.TabControl1.TabPages.Remove(ShadowMain.TabPage2)
            ShadowMain.TabControl1.TabPages.Remove(ShadowMain.TabPage3)

        ElseIf optFaculty.Checked = True Then
            ShadowMain.TabControl1.TabPages.Remove(ShadowMain.TabPage1)
            ShadowMain.TabControl1.TabPages.Remove(ShadowMain.TabPage3)

        ElseIf optDepartmentChair.Checked = True Then
            ShadowMain.TabControl1.TabPages.Remove(ShadowMain.TabPage1)
            ShadowMain.TabControl1.TabPages.Remove(ShadowMain.TabPage2)

        End If
    Else

        'if no radiobutton is selected display messagebox
        MsgBox("Please select a role")
        Exit Sub
    End If

    ' Check which role is selected and proceed accordingly


    '--------------------------------------------------------------------------------
    ' Student Role Login
    '--------------------------------------------------------------------------------
    If optStudent.Checked Then 'If user select a student role


        ' Let's Search for the User and Password

        cnnOLEDB.ConnectionString = strConnectionString
        cnnOLEDB.Open()
        ' Select the Student Record base on User Input
        cmdOLEDB.CommandText = "SELECT * FROM [Student] WHERE [SRedID]=" & txtRedID.Text
        cmdOLEDB.Connection = cnnOLEDB
        Dim rdrOLEDB As OleDbDataReader = cmdOLEDB.ExecuteReader

        'If we can find a match..
        If rdrOLEDB.Read = True Then
            ' See that the User, Password and Active status okay
            If rdrOLEDB.Item(0).ToString = txtRedID.Text And rdrOLEDB.Item(9).ToString = txtPassword.Text And rdrOLEDB.Item(13).ToString = "True" Then
                'Populate global userID (for future needs)
                userID = txtRedID.Text()
                'Populate a role for (for future needs)
                role = "Student"
                'Cleanup the login form
                Call LoginCleanup()
                ' Populate personal data in the Student Home
                ShadowMain.lblLName.Text = rdrOLEDB.Item(1).ToString
                ShadowMain.lblFName.Text = rdrOLEDB.Item(3).ToString
                ShadowMain.lblMIn.Text = rdrOLEDB.Item(2).ToString
                ShadowMain.lblAddOne.Text = rdrOLEDB.Item(5).ToString
                ShadowMain.lblCity.Text = rdrOLEDB.Item(6).ToString
                ShadowMain.lblState.Text = rdrOLEDB.Item(7).ToString
                ShadowMain.lblZip.Text = rdrOLEDB.Item(8).ToString
                ShadowMain.lblPhone.Text = rdrOLEDB.Item(10).ToString
                ShadowMain.lblEmail.Text = rdrOLEDB.Item(15).ToString
                'Show student home
                ShadowMain.Show()
                ' Close table and database connection (required) 
                rdrOLEDB.Close()
                cnnOLEDB.Close()
            Else
                'If user / password don't match
                MsgBox("Sorry, username or password not found", MsgBoxStyle.OkOnly, "Invalid Login")
                ' clear login window
                Call ClearLogin()
                ' Close table and database connection (required)
                rdrOLEDB.Close()
                cnnOLEDB.Close()
            End If
        Else
            ' Close table and database connection (required)
            rdrOLEDB.Close()
            cnnOLEDB.Close()
            'If user / password don't match
            MsgBox("Sorry, username or password not found", MsgBoxStyle.OkOnly, "Invalid Login")
            Call ClearLogin()
        End If


        '--------------------------------------------------------------------------------
        ' Faculty Role Login
        '--------------------------------------------------------------------------------

    ElseIf optFaculty.Checked Then

        ' Let's Search for the User and Password
        cnnOLEDB.Close()
        cnnOLEDB.ConnectionString = strConnectionString
        cnnOLEDB.Open()
        cmdOLEDB.CommandText = "SELECT * FROM [Faculty] WHERE [FRedID]=" & txtRedID.Text
        cmdOLEDB.Connection = cnnOLEDB
        Dim rdrOLEDB As OleDbDataReader = cmdOLEDB.ExecuteReader


        'If we can find a match.
        If rdrOLEDB.Read = True Then
            If rdrOLEDB.Item(0).ToString = txtRedID.Text And rdrOLEDB.Item(5).ToString = txtPassword.Text And rdrOLEDB.Item(9).ToString = "True" Then
                userID = txtRedID.Text()
                role = "Faculty"
                Call LoginCleanup()
                ShadowMain.lblLastNameFac.Text = rdrOLEDB.Item(2).ToString
                ShadowMain.lblFirstNameFac.Text = rdrOLEDB.Item(3).ToString
                ShadowMain.lblMiddleIntFac.Text = rdrOLEDB.Item(4).ToString
                ShadowMain.lblOfficeFac.Text = rdrOLEDB.Item(8).ToString
                ShadowMain.lblPhoneFac.Text = rdrOLEDB.Item(6).ToString
                ShadowMain.lblEmailFacl.Text = rdrOLEDB.Item(7).ToString
                ShadowMain.Show()
                rdrOLEDB.Close()
                cnnOLEDB.Close()
            Else
                MsgBox("Sorry, username or password not found", MsgBoxStyle.OkOnly, "Invalid Login")
                Call ClearLogin()
                rdrOLEDB.Close()
                cnnOLEDB.Close()
            End If
        Else
            rdrOLEDB.Close()
            MsgBox("Sorry, username or password not found", MsgBoxStyle.OkOnly, "Invalid Login")
            Call ClearLogin()
        End If



        '--------------------------------------------------------------------------------
        ' Department Chair Role Login
        '--------------------------------------------------------------------------------

    ElseIf optDepartmentChair.Checked Then
        ' Let's Search for the User and Password
        Dim rdrOLEDB As OleDbDataReader = cmdOLEDB.ExecuteReader
        cnnOLEDB.Close()
        cnnOLEDB.ConnectionString = strConnectionString
        cnnOLEDB.Open()
        cmdOLEDB.CommandText = "SELECT [DCRedID,Password] FROM [DepartmentChair] WHERE [DCRedID]=" & txtRedID.Text
        cmdOLEDB.Connection = cnnOLEDB


        'If we can find a match..
        If rdrOLEDB.Read = True Then
            If rdrOLEDB.Item(0).ToString = txtRedID.Text And rdrOLEDB.Item(1).ToString = txtPassword.Text Then
                userID = txtRedID.Text()
                role = "Department Chair"
                Call LoginCleanup()
                ShadowMain.Show()
                rdrOLEDB.Close()
                cnnOLEDB.Close()
            Else
                MsgBox("Sorry, username or password not found", MsgBoxStyle.OkOnly, "Invalid Login")
                Call ClearLogin()
                rdrOLEDB.Close()
                cnnOLEDB.Close()
            End If
        Else
            rdrOLEDB.Close()
            cnnOLEDB.Close()
            MsgBox("Sorry, username or password not found", MsgBoxStyle.OkOnly, "Invalid Login")
            Call ClearLogin()
        End If
    End If


End Sub

我现在遇到的问题是,如果我第一次登录失败,然后第二次尝试登录,我会收到错误消息:

Not allowed to change the 'ConnectionString' property. The connection's current state is open.

我查找并找到了一个解决方案,说我需要确保我的连接事先关闭,它解决了那个问题,但现在我遇到了这个问题:

Invalid attempt to call Read when reader is closed.

我试图尽可能最好地标记所有内容,并添加了我的大部分代码,因为人们总是要求查看它。 任何帮助表示赞赏。

我真的建议您将庞大的代码块拆分成更小的部分。实际上这段代码很难阅读和调试。为了控制连接状态,您不得不引入对 Connection.Close 和 DataReader.Close 的虚假调用,但是,如您所见,这很容易出错,因为您无法确定是否涵盖了所有代码路径。

相反,如果您引入更小的代码块,您可以更好地控制何时打开和关闭与关联 reader 的连接。

例如

If optStudent.Checked Then 'If user select a student role
    '--------------------------------------------------------------------------------
    ' Student Role Login
    '--------------------------------------------------------------------------------
   HandleStudentRole()
ElseIf optFaculty.Checked Then
    '--------------------------------------------------------------------------------
    ' Faculty Role Login
    '--------------------------------------------------------------------------------
     HandleFacultyRole()

ElseIf optDepartmentChair.Checked Then
    '--------------------------------------------------------------------------------
    ' Department Chair Role Login
    '--------------------------------------------------------------------------------
    HandleDepartmentRole()
End If

现在您可以编写更小的代码块,确保每个块都打开和关闭连接以及 reader(这里我将展示学生角色的块,但其他块类似)

Private Sub HandleStudenRole()
  ' Let's Search for the User and Password

    Using cnnOLEDB = new OleDbConnection(strConnectionString)
    Using cmdOleDB = new OleDbCommand("SELECT * FROM [Student] WHERE [SRedID]= @studentID", cnnOleDB)
       cnnOLEDB.Open()
       ' Select the Student Record base on User Input
       cmdOleDb.Parameters.Add("@studentID", OleDbType.VarWChar).Value = Convert.ToInt32(txtRedID.Text)
       Using rdrOLEDB = cmdOLEDB.ExecuteReader
           'If we can find a match..
          If rdrOLEDB.Read = True Then
             ......
          Else
            'If user / password don't match
            MsgBox(....)
            ' clear login window
            Call ClearLogin()
          End If
       End Using
    End Using
    End Using
End Sub

我使用了 Using statement 允许删除您为关闭连接而编写的所有代码和 reader。只要代码流从 using 块中退出,using 将确保调用 Close 和 Dispose 方法,如果您遇到异常也是如此。当然,查询是参数化的(尽管在这种情况下很难利用 Sql 注入)

另请注意,在我的 HandleStudentRole 块中,变量 cnnOLEDBcmdOLEDB 是本地变量变量。您不再需要在全局范围内声明它们。如果您在每次需要它们时减少并初始化它们,那么性能不会下降,并且代码的整洁度会好得多。