如何正确执行rd.HasRow而不影响将照片上传到数据库?

时间:2018-09-26 07:49:48

标签: sql vb.net sqldatareader

我正在尝试使用rd.HasRow方法来验证键入的数据在保存到数据库之前是否重复。

如果重复,则假定弹出错误消息框而不是保存数据。

我该如何执行此操作以及将照片上传到数据库的代码?如果我注释了这部分代码,可以将键入的数据(不重复)保存到数据库中,但是照片不会随照片一起上传。

'i = cmd.ExecuteNonQuery()
'If i >= 1 Then
    'MessageBox.Show("Profile successfully registered!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
'Else
    'MessageBox.Show("Error. Please try again later.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
'End If

但是,如果我不这样做,将不会保存用户键入的数据,并且会针对i=cmd.ExecuteNonQuery()弹出此错误消息:

  

System.InvalidOperationException:'已经存在与此Command关联的打开的DataReader,必须先关闭它。'

这是整体代码。

Private Sub button2_Click(sender As Object, e As EventArgs) Handles button2.Click
    Dim con As New SqlConnection
    Dim cmd As New SqlCommand

    Dim rollno As String
    Dim name As String
    Dim gender As String
    Dim address As String
    Dim phoneno As Integer
    Dim datereg As String
    Dim faculty As String
    Dim course As String
    Dim semester As String
    Dim i As Integer
    Dim j As Integer

    rollno = TextBox1.Text
    name = TextBox2.Text
    gender = ComboBox4.Text
    address = TextBox3.Text
    phoneno = TextBox4.Text
    datereg = dateTimePicker1.Value
    faculty = comboBox1.Text
    course = comboBox2.Text
    semester = comboBox3.Text

    con.ConnectionString = "Data Source=LAPTOP-85ALBAVS\SQLEXPRESS;Initial Catalog=Portal;Integrated Security=True"
    cmd.Connection = con
    con.Open()

    'To validate whether duplication of typed in data by user occurs or not, if yes, error msg pop-up. If no, proceed and save the data into database
    Dim rd As SqlDataReader
    cmd.CommandText = "SELECT * FROM Profile WHERE RollNo= '" & TextBox1.Text & "' and Name='" & TextBox2.Text & "'"
    rd = cmd.ExecuteReader()
    If rd.HasRows Then
        MessageBox.Show("User already registered! Please try again.", "Error", MessageBoxButtons.OK)
    Else
        cmd.CommandText = "INSERT INTO Profile VALUES ('" & rollno & "' , '" & name & "' , '" & gender & "' , '" & address & "' , '" & phoneno & "' , '" & datereg & "' , '" & faculty & "' , '" & course & "' , '" & semester & "')"
    End If
    'i = cmd.ExecuteNonQuery()
    'If i >= 1 Then
    'MessageBox.Show("Profile successfully registered!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
    'Else
    'MessageBox.Show("Error. Please try again later.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
    'End If
    con.Close()

    con.Open()
    'To save the uploaded photo to table Photo

    Dim command As New SqlCommand("Insert into Photo (Img, Pid) Values (@Img, @Pid)", con)
    command.Connection = con
    Dim ms As New MemoryStream
    pictureBox1.Image.Save(ms, pictureBox1.Image.RawFormat)
    command.Parameters.Add("@Img", SqlDbType.Image).Value = ms.ToArray()
    command.Parameters.Add("@Pid", SqlDbType.VarChar).Value = TextBox1.Text

    j = cmd.ExecuteNonQuery()
    If j >= 1 Then
        MessageBox.Show("Profile successfully registered!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
    Else
        MessageBox.Show("Error. Please try again later.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
    End If
End Sub

2 个答案:

答案 0 :(得分:1)

代码看起来有些杂乱,至少以我的经验,调试杂乱的代码可能很困难。我们可以采取一些措施来纠正该问题,我现在将尝试与您一起解决。

首先,为控件添加有意义的名称。您可以通过选择控件并更改Name属性在表单上进行设计。通过代码引用它们时,这将极大地帮助您。在这种情况下,它还将帮助您消除对变量的需求。

考虑实施Using

  

有时,您的代码需要不受管的资源,例如文件句柄,COM包装程序或SQL连接。使用代码块可以保证在您的代码完成后,处置一个或多个此类资源。这使它们可供其他代码使用。

这将帮助您管理声明和资源,同时使代码更清晰。

我还考虑将每个命令分成自己的Using块,以使代码更清晰。

将数据插入数据库时​​,请考虑使用SQL parameters来避免SQL injection

最后进入代码,让我们依次查看每个Using块。

首先,我将在SqlConnection块中启动Using,然后为每个命令使用该连接:

Using con As New SqlConnection("Data Source=LAPTOP-85ALBAVS\SQLEXPRESS;Initial Catalog=Portal;Integrated Security=True")

    con.Open()

    'Add the rest of the code here

End Using

检查记录是否存在:

在这里,考虑声明一个Boolean变量,我们将使用该变量来确定记录是否存在。

Dim recordExists As Boolean = False
Using cmd As New SqlCommand("SELECT * FROM Profile WHERE RollNo = @RollNo AND Name = @Name", con)
    cmd.Parameters.Add("@RollNo", SqlDbType.[Type]).Value = txtRollNo.Text
    cmd.Parameters.Add("@Name", SqlDbType.[Type]).Value = txtName.Text

    Using reader As SqlDataReader = cmd.ExecuteReader()
        recordExists = reader.HasRows
    End Using
End Using

显示记录是否存在的提示,如果不存在则插入数据库:

If recordExists Then
    MessageBox.Show("User already registered! Please try again.", "Error", MessageBoxButtons.OK)
Else
    Using cmd As New SqlCommand("INSERT INTO Profile VALUES (@RollNo, @Name, @Gender, @Address, @PhoneNo, @DateReg, @Faculty, @Course, @Semester)", con)

        cmd.Parameters.Add("@RollNo", SqlDbType.[Type]).Value = txtRollNo.Text
        cmd.Parameters.Add("@Name", SqlDbType.[Type]).Value = txtName.Text
        cmd.Parameters.Add("@Gender", SqlDbType.[Type]).Value = cboGender.Text
        cmd.Parameters.Add("@Address", SqlDbType.[Type]).Value = txtAddress.Text
        cmd.Parameters.Add("@PhoneNo", SqlDbType.[Type]).Value = txtPhoneNo.Text
        cmd.Parameters.Add("@DateReg", SqlDbType.[Type]).Value = dtpDateReg.Value
        cmd.Parameters.Add("@Faculty", SqlDbType.[Type]).Value = cboFaculty.Text
        cmd.Parameters.Add("@Course", SqlDbType.[Type]).Value = cboCourse.Text
        cmd.Parameters.Add("@Semester", SqlDbType.[Type]).Value = cboSemster.Text

        If cmd.ExecuteNonQuery() > 0 Then
            MessageBox.Show("Profile successfully registered!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else
            MessageBox.Show("Error. Please try again later.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End If
    End Using
End If

插入图像:

Using cmd As New SqlCommand("INSERT INTO Photo (Img, Pid) VALUES (@Img, @Pid)", con)

    Using ms As New MemoryStream()
        pbxImage.Image.Save(ms, pbxImage.Image.RawFormat)

        cmd.Parameters.Add("@Img", SqlDbType.Image).Value = ms.ToArray()
        cmd.Parameters.Add("@Pid", SqlDbType.VarChar).Value = txtName.Text
    End Using

    cmd.ExecuteNonQuery()
End Using
  

请注意,我不确定您在数据库中的数据类型时使用了SqlDbType.[Type]。您将要用为每一列指定的数据类型替换它。

所有代码都看起来像这样:

Using con As New SqlConnection("Data Source=LAPTOP-85ALBAVS\SQLEXPRESS;Initial Catalog=Portal;Integrated Security=True")

    con.Open()

    Dim recordExists As Boolean = False
    Using cmd As New SqlCommand("SELECT * FROM Profile WHERE RollNo = @RollNo AND Name = @Name", con)
        cmd.Parameters.Add("@RollNo", SqlDbType.VarChar).Value = txtRollNo.Text
        cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = txtName.Text

        Using reader As SqlDataReader = cmd.ExecuteReader()
            recordExists = reader.HasRows
        End Using
    End Using

    If recordExists Then
        MessageBox.Show("User already registered! Please try again.", "Error", MessageBoxButtons.OK)
    Else
        Using cmd As New SqlCommand("INSERT INTO Profile VALUES (@RollNo, @Name, @Gender, @Address, @PhoneNo, @DateReg, @Faculty, @Course, @Semester)", con)

            cmd.Parameters.Add("@RollNo", SqlDbType.[Type]).Value = txtRollNo.Text
            cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = txtName.Text
            cmd.Parameters.Add("@Gender", SqlDbType.VarChar).Value = cboGender.Text
            cmd.Parameters.Add("@Address", SqlDbType.VarChar).Value = txtAddress.Text
            cmd.Parameters.Add("@PhoneNo", SqlDbType.VarChar).Value = txtPhoneNo.Text
            cmd.Parameters.Add("@DateReg", SqlDbType.VarChar).Value = dtpDateReg.Value
            cmd.Parameters.Add("@Faculty", SqlDbType.VarChar).Value = cboFaculty.Text
            cmd.Parameters.Add("@Course", SqlDbType.VarChar).Value = cboCourse.Text
            cmd.Parameters.Add("@Semester", SqlDbType.VarChar).Value = cboSemster.Text

            con.Open()

            If cmd.ExecuteNonQuery() > 0 Then
                MessageBox.Show("Profile successfully registered!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Else
                MessageBox.Show("Error. Please try again later.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End If
        End Using
    End If

    Using cmd As New SqlCommand("INSERT INTO Photo (Img, Pid) VALUES (@Img, @Pid)", con)

        Using ms As New MemoryStream()
            pbxImage.Image.Save(ms, pbxImage.Image.RawFormat)

            cmd.Parameters.Add("@Img", SqlDbType.Image).Value = ms.ToArray()
            cmd.Parameters.Add("@Pid", SqlDbType.VarChar).Value = txtName.Text
        End Using

        con.Open()

        cmd.ExecuteNonQuery()
    End Using

End Using

该代码未经测试,我没有使用环境,但是它应该可以为您提供一些帮助。

答案 1 :(得分:0)

在线发表评论和解释。

Private Sub OPCode()
        Dim i As Integer
        Dim j As Integer
        Dim rollno = TextBox1.Text
        Dim name = TextBox2.Text
        Dim gender = ComboBox4.Text
        Dim address = TextBox3.Text
        Dim phoneno = CInt(TextBox4.Text) 'Unless your phone numbers are very different
        'than the phone numbers here, the likelyhood of a user entering just numbers is
        'nil. Change this to a string and a VarChar in the database
        Dim datereg = dateTimePicker1.Value
        Dim faculty = comboBox1.Text
        Dim course = ComboBox2.Text
        Dim semester = ComboBox3.Text
        'The Using block ensures that your connection is closed and disposed
        'Pass your connection string to the constructor of the connection
        Using con As New SqlConnection("Data Source=LAPTOP-85ALBAVS\SQLEXPRESS;Initial Catalog=Portal;Integrated Security=True")
            'Pass the Sql command text and connection to the Constructor of the command.
            'NEVER, NEVER, NEVER allow user input to be passed directly to a database. Always use parameters.
            Dim cmd As New SqlCommand("SELECT * FROM Profile WHERE RollNo= @RollNo and [Name]= @Name;", con)
            cmd.Parameters.Add("@RollNo", SqlDbType.VarChar).Value = rollno
            cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = name
            con.Open()
            Using rd As SqlDataReader = cmd.ExecuteReader()
                'To validate whether duplication of typed in data by user occurs or not, if yes, error msg pop-up. If no, proceed and save the data into database
                If rd.HasRows Then
                    MessageBox.Show("User already registered! Please try again.", "Error", MessageBoxButtons.OK)
                    'You don't want to go any further if the user is registered.
                    Exit Sub
                End If
            End Using
            'Just use another new command variable to avoid confusion
            'I think it is much better practice to list the fields.
            Dim cmd2 As New SqlCommand("INSERT INTO Profile VALUES (@RollNo ,@Name,@Gender, @Address, @PhoneNo , @DateReg , @Faculty , @Course , @Semester);", con)
            cmd2.Parameters.Add() 'etc.
            i = cmd2.ExecuteNonQuery()
            If i >= 1 Then
                MessageBox.Show("Profile successfully registered!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Else
                MessageBox.Show("Error. Please try again later.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Exit Sub
            End If
            'To save the uploaded photo to table Photo
            Dim command3 As New SqlCommand("Insert into Photo (Img, Pid) Values (@Img, @Pid)", con)
            command3.Connection = con
            Dim ms As New MemoryStream
            pictureBox1.Image.Save(ms, pictureBox1.Image.RawFormat)
            command3.Parameters.Add("@Img", SqlDbType.Image).Value = ms.ToArray()
            command3.Parameters.Add("@Pid", SqlDbType.VarChar).Value = TextBox1.Text

            j = command3.ExecuteNonQuery()
        End Using
        If j >= 1 Then
                MessageBox.Show("Profile successfully registered!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Else
                MessageBox.Show("Error. Please try again later.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End If
    End Sub