如何解决:“已经有一个打开的 DataReader 与此命令关联,必须首先关闭它。

How to resolve : 'There is already an open DataReader associated with this Command which must be closed first.'

提问人:Josiah Parada 提问时间:2/9/2023 更新时间:2/9/2023 访问量:80

问:

我一直在尝试将数据插入我的sql数据库,但这个问题总是出现 我尝试再次重做,但出现了同样的问题,我现在真的很困惑

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

        Dim conn As SqlConnection = New SqlConnection("Data Source=DESKTOP-OBQR58O\SQLEXPRESS;Initial Catalog=Accounts;Integrated Security=True")
        Dim comm As SqlCommand = New SqlCommand("insert into User(username, password)values('" + TextBox1.Text + "', '" + TextBox3.Text + "')", conn)
        Dim data As SqlDataAdapter = New SqlDataAdapter(comm)

        Dim user = TextBox1.Text
        Dim pass = TextBox2.Text
        Dim cpass = TextBox3.Text

        Dim reader As SqlDataReader
        conn.Open()
        Dim cmd As SqlCommand = New SqlCommand("select Username from [User] where Username ='" + TextBox1.Text + "'", conn)
        conn.Close()
        conn.Open()
        reader = cmd.ExecuteReader

        If user.Trim() = "" Or pass.Trim() = "" Or cpass.Trim() = "" Then
            MessageBox.Show("Empty Fields", "Blank Spaces")

        ElseIf Not String.Equals(pass, cpass) Then
            MessageBox.Show("Passwords do not match", "ERROR")
            conn.Close()

        ElseIf reader.HasRows Then
            MessageBox.Show("Username already exists!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            TextBox1.Clear()
            conn.Close()
            reader.Close()

        Else
            MessageBox.Show("Account created succesfully!", "Success")
            Dim table As DataTable = New DataTable()
            data.Fill(table) ' this is where the problem occurs.
            TextBox1.Clear()
            TextBox2.Clear()
            TextBox3.Clear()
            Dim log As New Login
            Me.Close()
            log.Show()
            conn.Close()
        End If
        conn.Close()
    End Sub

老实说,我不知道该怎么办

SQL Server 数据库 vb.net SSMS

评论

3赞 Sean Lange 2/9/2023
您正在以明文形式存储密码。这是边缘犯罪。密码应加盐和散列。它们绝不应以明文形式存储或使用两种加密方法。您的代码也对 sql 注入完全开放。您需要阅读、理解并开始参数化您的查询。您应该将连接信息放在配置文件中,而不是放在您需要的任何位置。
1赞 Thom A 2/9/2023
我只需输入我的密码,然后继续前进,我想......' OR 1=1; SELECT Username, Password FROM [User]--
0赞 Ann L. 2/16/2023
到目前为止取得了哪些进展?
0赞 Josiah Parada 2/21/2023
你好!对不起,回复晚了,它终于奏效了!@AnnL。
0赞 Ann L. 2/22/2023
如果我的答案帮助你解决了你的问题,请考虑将其标记为你接受的答案!谢谢!

答:

1赞 Ann L. 2/9/2023 #1

你在顶部打开你的阅读器:

reader = cmd.ExecuteReader

所以,它是开放的。然后,当您运行该命令时,它会与打开的读取器发生冲突!Fill

最简单的解决方法 - 尽管就我个人而言,我会稍微重构代码,以使其更接近使用位置 - 是在 .OpenReaderCloseFill

         Else
            reader.Close()  ' what you would add
            MessageBox.Show("Account created succesfully!", "Success")
            Dim table As DataTable = New DataTable()
            data.Fill(table) ' this is where the problem occurs.

非常重要:如果您不熟悉“SQL注入攻击”的概念,请立即阅读它们。切勿执行通过使用来自用户的未经验证的数据构造字符串来构建的 SQL。您应该改为传递参数。

毕竟,如果我输入用户名“无关紧要”怎么办;DROP TABLE 用户;--“?你最终会得到一个包含"SELECT Username from [Users] WHERE [Username] = 'Irrelevant'; DROP TABLE Users; --'"

当然,您还应该验证输入,例如嵌入式 HTML 和脚本!但这比仅仅使用 SQL 参数要复杂得多。

评论

0赞 Josiah Parada 2/9/2023
你好!谢谢你的建议,我会在早上第一件事就尝试一下,这只是一个用基本编码知识完成的学校项目,所以这是我目前只能做的
0赞 Ann L. 2/12/2023
调试有什么进展吗?