Как правильно выполнить rd.HasRow, не влияя на загрузку фотографии в базу данных? - PullRequest
0 голосов
/ 26 сентября 2018

Я пытаюсь использовать метод 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: 'Уже существует открытый 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 голосов
/ 26 сентября 2018

Код выглядит немного грязно, и, по моему опыту, по крайней мере, это может быть трудно отладить грязный код.Есть несколько вещей, которые мы можем сделать, чтобы исправить это, и я попытаюсь сделать это сейчас с вами.

Во-первых, дайте значимые имена вашим элементам управления.Это можно сделать с помощью дизайна формы, выбрав элемент управления и изменив свойство Name.Это очень поможет вам при обращении к ним через код.В этом случае это также поможет вам устранить необходимость в переменных.

Рассмотрите возможность реализации Использование :

Иногда вашему коду требуется неуправляемый ресурс, такой как дескриптор файла, оболочка COM или соединение SQL.Блок Using гарантирует удаление одного или нескольких таких ресурсов, когда ваш код закончен с ними.Это делает их доступными для использования другим кодом.

Это поможет вам управлять вашими объявлениями и ресурсами, а также создавать более четкое представление о вашем коде.

Я бы также рассмотрел возможность нарушения каждого из них.введите собственный блок Using, чтобы сделать ваш код более понятным.

При вставке данных в базу данных рассмотрите возможность использования параметров SQL , чтобы избежать SQL-инъекции .

Наконец, в коде, давайте посмотрим на каждый блок 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

Этот кодне протестирован, у меня нет среды, но она должна дать вам кое-что для работы.

0 голосов
/ 26 сентября 2018

Комментарии и пояснения в строке.

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
...