2016-02-28 102 views
0

我想實現一個文本框,即txtSearchInput即能搜索會員ID(自動編號)以及會員名(短文本)來自MS Access數據庫的VB.NET數據類型不匹配

如果我進入到文本框基於會員ID搜索成員,我好去。但是,我收到此錯誤消息:Data type mismatch in criteria expression.如果我試圖根據成員名稱搜索成員。

有沒有人可以向我解釋我應該如何編碼才能正確使用?此外,如果你們有鏈接,如果這個問題以前的答案或更好的概念,我會高度讚賞它。

我當前的代碼:

Try 
    'Setup Connection String 
    conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " & Application.StartupPath & "\igcDatabase.accdb" 
    sqlCom.Connection = conn 

    'Open Data Connection 
    conn.Open() 

    'Query 
    sqlCom.CommandText = "SELECT * FROM [Members] WHERE [Member ID] = @MemberID OR [Member First Name] = @FirstName" 

    'Parameter is used below to prevent SQL Injection 
    sqlCom.Parameters.AddWithValue("MemberID", txtSearchInput.Text) 
    sqlCom.Parameters.AddWithValue("FirstName", txtSearchInput.Text) 

    Dim sqlRead As OleDbDataReader = sqlCom.ExecuteReader() 

    sqlRead.Read() 

    If sqlRead.HasRows = True Then 

     Dim membershipType As String 
     If sqlRead.GetValue(4) = 1 Then 
      membershipType = "Deluxe" 
     ElseIf sqlRead.GetValue(4) = 2 Then 
      membershipType = "Non-Deluxe" 
     Else 
      membershipType = "Week-Day" 
     End If 

     txtMemberID.Text = sqlRead.GetValue(0) 
     txtFirstName.Text = sqlRead.GetString(1) 
     txtLastName.Text = sqlRead.GetString(2) 
     txtGender.Text = sqlRead.GetString(3) 
     txtContact.Text = sqlRead.GetValue(5) 
     txtEmail.Text = sqlRead.GetString(6) 
     txtMembershipType.Text = membershipType 
     txtStatus.Text = sqlRead.GetString(7) 
    Else 
     MessageBox.Show("There Is no such member found in database. Please Try again. ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning) 
     txtSearchInput.Clear() 
     txtSearchInput.Focus() 
    End If 
    sqlCom.Parameters.Clear() 
    sqlRead.Close() 
    conn.Close() 
Catch ex As Exception 
    MessageBox.Show(ex.Message) 
End Try 
+1

如果'會員ID'是一個值,你逝去的文本是一個字符串;完整的錯誤信息會這樣說。您應該使用'Add'而不是'AddWithValue'並指定類型。它看起來像選項嚴格關閉 – Plutonix

+0

@Plutonix感謝您的解決方案,它真的幫了我很多!而且,選項嚴格關閉。如果最好在默認情況下打開它? – Gideon

+1

最好使它成爲所有項目的永久默認值:工具 - >選項 - >項目和解決方案 - > VB默認值。可能還需要爲當前項目打開它:項目屬性 - >編譯 – Plutonix

回答

0

你有兩種可能性來搜索,它將使意義有兩個查詢,選擇哪一種取決於如果輸入值是一個數字或沒有。您可以使用Int32.TryParse來檢查。

的其他一些觀點:

  • 你應該明確地說明你想從數據庫中檢索,讓你知道他們是在您需要的順序列。

  • 我已經使用Using塊來確保數據庫訪問命令使用的任何非託管資源的清理處理。

  • 有兩個成員有相同的名字的機會,你應該編寫一些東西來處理這種情況。

  • 請參閱代碼中的評論和TODO。

這是我想出了(未經測試):

Option Infer On 
Option Strict On 

Imports System.Data.OleDb 
Imports System.IO 
'... 
Sub x() 
    Dim criterionValue = txtSearchInput.Text 
    Dim colsToRetrieve = "[Member ID], [Member First Name], [Member Last Name], [MembershipType], [Gender], [Contact], [Email], [Status]" 
    Dim memID As Integer 
    Dim sql As String 
    Dim param As OleDbParameter 

    ' Use different queries depending on if the user entered a number to search for or text. 
    If Int32.TryParse(criterionValue, memID) Then 
     sql = "SELECT " & colsToRetrieve & " FROM [Members] WHERE [Member ID] = @MemberID" 
     param = New OleDbParameter With {.ParameterName = "@MemberID", .OleDbType = OleDbType.Integer, .Value = memID} 
    Else 
     sql = "SELECT " & colsToRetrieve & " FROM [Members] WHERE [Member First Name] = @FirstName" 
     'TODO: set .Size to the size declared in the database 
     param = New OleDbParameter With {.ParameterName = "@FirstName", .OleDbType = OleDbType.VarWChar, .Size = 50, .Value = criterionValue} 
    End If 

    ' let the ConnectionStringBuilder take care of any quoting of the path... 
    Dim connStr As New OleDbConnectionStringBuilder 
    connStr.Provider = "Microsoft.ACE.OLEDB.12.0" 
    'TODO: move the database to somewhere it will work properly, 
    ' see https://msdn.microsoft.com/en-us/library/system.environment.specialfolder%28v=vs.110%29.aspx 
    connStr.DataSource = Path.Combine(Application.StartupPath, "igcDatabase.accdb") 

    Try 
     ' use Using to take care of disposing of conn and sqlCmd... 
     Using conn As New OleDb.OleDbConnection(connStr.ConnectionString) 
      Using sqlCmd As New OleDbCommand(sql, conn) 
       sqlCmd.Parameters.Add(param) 
       conn.Open() 
       Dim rdr = sqlCmd.ExecuteReader() 

       If rdr.HasRows Then 
        Dim rowCount As Integer = 0 

        While rdr.Read() 
         Dim membershipType As String 

         Select Case rdr.GetInt32(4) 
          Case 1 
           membershipType = "Deluxe" 
          Case 2 
           membershipType = "Non-Deluxe" 
          Case Else 
           membershipType = "Week-Day" 
         End Select 

         txtMemberID.Text = rdr.GetInt32(0).ToString() 
         txtFirstName.Text = rdr.GetString(1) 
         txtLastName.Text = rdr.GetString(2) 
         txtGender.Text = rdr.GetString(3) 
         txtMembershipType.Text = membershipType 
         txtContact.Text = rdr.GetString(5) 
         txtEmail.Text = rdr.GetString(6) 
         txtStatus.Text = rdr.GetString(7) 

         rowCount += 1 

        End While 

        If rowCount > 1 Then 
         'TODO: Do something more useful than tell the user, e.g. present all the records. 
         MsgBox("More than one record found. Only the last is shown.") 
        End If 

       Else 
        MessageBox.Show("There is no such member found in database. Please try again. ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning) 
        ' User may have mis-typed just one character, don't make them type it all again 
        'txtSearchInput.Clear() 
        txtSearchInput.Focus() 

       End If 

       rdr.Close() 
      End Using 
     End Using 

    Catch ex As Exception 
     MsgBox(ex.Message) 
    End Try 

End Sub 
+0

感謝您的幫助!一旦我回到我的電腦,肯定會嘗試它並將回答標記爲答案。 – Gideon