2012-03-14 3 views
2

Я пытаюсь создать свою первую программу, и у меня возникли проблемы с SQL.Vb, ошибка оператора SQL. Не могу понять это

У меня есть база данных с клиентами и сотрудниками (между прочим), и я пытаюсь настроить основной экран входа. Пользователи регистрируются с их EmployeeID (первичный ключ)

В этой части рассматривается вход в систему в первый раз.

Он проверяет базу данных для пользователя с этим идентификатором и захватывает пароль. Если пароль не пуст/null, он показывает окно сообщения и останавливается там.

Если пароль пуст/null, он предназначен для подтверждения и последующего обновления нового пароля.

Здесь я заканчиваю свое понимание. Отладка показывает, что ошибка определенно находится в обновлении SQL, но я не вижу никаких ошибок ...

Помощь?

Спасибо.

код следующим образом:

Private Sub NewPass() 
    Dim PassCheck As String 
    GetDatabase() 
    'Check if there is a password 
    SQLString = "SELECT EmployeeID, Password, Deleted FROM Employee " 
    SQLString += "WHERE EmployeeID= " & UserID 
    Try 
     connection.Open() ' Open Connection 
     If ConnectionState.Open.ToString = "Open" Then 
      command = New System.Data.OleDb.OleDbCommand(SQLString, connection) 
      datareader = command.ExecuteReader() 
      If datareader.HasRows Then 
        If datareader.Item("Deleted") = False Then 
        'Password check 
        outputString = datareader.Item("Password").ToString 
        Else 
         outputString = "" 
        End If 
      End If 'recordset has rows 
      datareader.Close() 
     End If 
    Catch ex As Exception 'Display Error message 
     MessageBox.Show("Error accessing database", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) 
    End Try 
    connection.Close() 

    PassCheck = outputString 

    If String.IsNullOrEmpty(PassCheck) = True Then 

     GetDatabase() 
     SQLString = "UPDATE Employee SET " 
     SQLString += "Password = '" & Password & "' " 
     SQLString += "WHERE EmployeeID = " & UserID 
     'Try 
     connection.Open() 
     If ConnectionState.Open.ToString = "Open" Then 
      'Update Password 
      command = New System.Data.OleDb.OleDbCommand(SQLString, connection) 
      command.ExecuteNonQuery() 

      MainMenuForm.Show() 
      Me.Hide() 
     Else 
      outputString = "" 
      MessageBox.Show("Error opening connection") 
     End If 
     connection.Close() 
     'Catch ex As Exception 

     'End Try 
    Else 
     MessageBox.Show("This Account has a password", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) 
     FirstTimeButton.Show() 
     FirstTimeBool = False 
    End If 

End Sub 

GetDatabase()

Private Sub GetDatabase() 
    'Locates the Database 
    Try 
     ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data " 
     ConnectionString += "Source=" & System.Windows.Forms.Application.StartupPath & "\PharmacyDatabase.accdb " 
     connection = New System.Data.OleDb.OleDbConnection(ConnectionString) 
    Catch ex As Exception 'No Database Found 
     MessageBox.Show("No Database Found in \Debug", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) 
    End Try 
End Sub 
+1

Это похоже, что вы храните пароли открытого текста в базе данных, и это очень плохая идея. Также похоже, что ваши запросы будут уязвимы для SQL-инъекций. –

+0

Что такое связь? Где он создан? Что делает GetDatabase()? Кроме того, «Если ConnectionState.Open.ToString =« Открыть », всегда будет считаться истинным. Вы хотите проверить connection.ConnectionState == ConnectionState.Open –

+0

Является ли ваша переменная пароля установленной вне этой функции, или это ничего, когда вы строите свой SQL-запрос обновления? –

ответ

5

Я ненавижу быть носителем плохие новости, но есть только так много плохого там, в том числе несколько серьезных проблем безопасности и потенциальный отказ в обслуживании. Попробуйте код ниже. Вам нужна библиотека BCrypt доступна здесь:
http://derekslager.com/blog/posts/2007/10/bcrypt-dotnet-strong-password-hashing-for-dotnet-and-mono.ashx

Во-первых, новый GetDatabase() функцию:

Private Function GetDatabase() As OleDbConnection 
    Return New System.Data.OleDbOleDbConnection(string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}\PharmacyDatabase.accdb", System.Windows.Forms.Application.StartupPath)) 
End Function 

Это нелогично, но благодаря связи объединяющие это действительно лучше в .NET для создания нового соединения каждый раз.

Тогда основная функция:

Private Sub NewPass() 
    Dim sql As String = "UPDATE Employee SET Password = ? WHERE EmployeeID= ? AND Password IS NULL" 
    Dim resultCount As Integer 
    Using cn As System.Data.OleDb.OleDbCommand = GetDatabase(), _ 
      command As New System.Data.OleDb.OleDbCommand(sql, cn) 

     command.Parameters.Add("Password", OleDbType.Char, 60).Value = BCrypt.HashPassword(password, BCrypt.GenerateSalt(12)) 
     command.Parameters.Add("UserID", OleDbType.Integer).Value = UserId 

     cn.Open() 
     resultCount = command.ExecuteNonQuery() 
    End Using 

    If resultCount <> 1 Then 
     'If a password was already set (password field not null), resultCount will be zero 
     MessageBox.Show("This Account does not exist or already has a password", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) 
     FirstTimeButton.Show() 
     FirstTimeBool = False 
    Else 
     MainMenuForm.Show() 
     Me.Hide() 
    End If 

End Sub 

Есть в этом коде несколько вещей, которые полностью отсутствует, и поэтому я хочу объяснить, куда они пошли. Во-первых, нет connection.Close(). Это полностью обрабатывается блоком «Использование» и обрабатывается лучше, потому что блок «Использование» обеспечивает закрытие соединения, даже если выбрано исключение.

Далее следует блок Try/Catch. Я чувствую, что это неправильный уровень кода для проверки ошибок. Замечательная вещь об исключениях заключается в том, что они поднимаются вверх по стеку. Обычно лучше сохранить вашу попытку/улов для кода ближе к пользовательскому интерфейсу, так как обычно лучше знать, как реагировать. Поэтому код, который напрямую связывается с базой данных, должен просто позволить исключению, и бизнес-уровень или уровень представления могут решить, что с ним делать.

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

+0

Я просто использую это как невероятно основную первую попытку в vb/sql без опыта. Пароль такой, потому что это не важно. Я больше беспокоюсь о том, чтобы просто научиться правильно обновлять таблицу прямо сейчас. – PatPat

+0

Это действительно полезно, кстати. Спасибо. Хотя я мог бы оставить свое исследование BCrypt еще на один день. – PatPat

+0

В этом случае просто напишите часть пароля в задней части вашего ума для дальнейшего использования. Остальная часть этого кода по-прежнему очень важна, поскольку важно использовать блок «Использование» для закрытия соединения, параметры запроса, ExecuteNonQuery и его возвращаемое значение, не нужно проверять состояние соединения после вызова .Open() на короткометражном соединений и т. д. –

0

У вас есть следующие в вашем коде как часть UPDATE заявления:

SQLString += "Password = '" & Password & "' " 

Однако, я не вижу, где у вас есть переменная с именем Password. Я вижу PassCheck, но не Password.

+0

Пароль объявляется в верхней части класса как String, как и UserID (как целое). Он доступен для NewPass(). – PatPat

Смежные вопросы