2017-04-05 47 views
-1

我有2個存儲過程(InsertToCustomer)和(InsertToRepair),我需要在一個按鈕單擊事件下運行。然而,當我按一下按鈕只有InsertToRepair程序的工作原理,並將其存儲在「修復」表,但沒有對客戶信息的獲取存儲在「客戶」表在按鈕單擊事件上執行2個存儲過程vb.net

下面是本

我vb.Net代碼與我看到的代碼
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles btnBookRepair.Click 
    'Declare variables 

    Dim bookedInBy, deviceType, bookedInDate, fName, lName, address, contactNum, altContactNum, deviceName, accessories, devicePassword, repairType, technicalNotes, repairStatus, completedNotes As String 
    Dim trackingNum As Integer 

    'Setting Date 

    bookedInDate = txtBookedInDate.Text 

    'Assigning variables 
    bookedInBy = DDLBookedInBy.SelectedItem.Text 
    deviceType = DDLDeviceType.SelectedItem.Text 
    trackingNum = txtTrackingNumber.Text 
    fName = txtFname.Text 
    lName = txtLname.Text 
    address = txtAddress.Text 
    contactNum = txtContactNum.Text 
    altContactNum = txtAltContactNum.Text 
    deviceName = txtDeviceName.Text 
    accessories = DDLAccessories.SelectedItem.Text 
    devicePassword = txtDevicePassword.Text 
    repairType = DDLRepairType.SelectedItem.Text 
    technicalNotes = txtTechnical.Text 
    repairStatus = DDLRepairStatus.SelectedItem.Text 
    completedNotes = txtCompletedNotes.Text 


    Dim sqlCS As String 

    sqlCS = ConfigurationManager.ConnectionStrings("Database").ConnectionString 
    Try 
     Using sqlConn As New SqlConnection(sqlCS) 
      Dim sqlCmd As New SqlCommand 

      sqlCmd.Connection = sqlConn 
      sqlCmd.CommandText = "InsertToRepair" 
      sqlCmd.CommandType = Data.CommandType.StoredProcedure 

      sqlConn.Open() 
      sqlCmd.ExecuteNonQuery() 

      sqlCmd.Parameters.AddWithValue("@Tracking_Number", trackingNum) 
      sqlCmd.Parameters.AddWithValue("@Booked_in_by", bookedInBy) 
      sqlCmd.Parameters.AddWithValue("@Device_Type", deviceType) 
      sqlCmd.Parameters.AddWithValue("@Booked_In_Date", bookedInDate) 
      sqlCmd.Parameters.AddWithValue("@Device_Name", deviceName) 
      sqlCmd.Parameters.AddWithValue("@Accessories", accessories) 
      sqlCmd.Parameters.AddWithValue("@DevicePassword", devicePassword) 
      sqlCmd.Parameters.AddWithValue("@Repair_Type", repairType) 
      sqlCmd.Parameters.AddWithValue("@Technical_Notes", technicalNotes) 
      sqlCmd.Parameters.AddWithValue("@Completed_Notes", completedNotes) 
      sqlCmd.Parameters.AddWithValue("@RepairStatus", repairStatus) 

      sqlCmd.ExecuteNonQuery() 

      sqlCmd.CommandText = "InsertToCustomer" 
      sqlCmd.CommandType = Data.CommandType.StoredProcedure 

      sqlCmd.Parameters.AddWithValue("@First_Name", fName) 
      sqlCmd.Parameters.AddWithValue("@Last_Name", lName) 
      sqlCmd.Parameters.AddWithValue("@ContactNumber", contactNum) 
      sqlCmd.Parameters.AddWithValue("@Alternative_Contact_Number", altContactNum) 
      sqlCmd.Parameters.AddWithValue("@CustomerAddress", address) 

      sqlConn.Close() 

     End Using 

    Catch ex As Exception 

     StatusLabel.Text = ex.ToString 


    End Try 

End Sub 
+1

您需要再次執行查詢。與您正在修理的內容相同。重新使用sqlCmd.ExecuteNonQuery()來執行SQL命令以將數據插入到客戶表中 – rach

+1

某些事情不對。在設置參數之前執行InsertToRepair。如果SP需要參數,則應該得到一個異常。然後再次執行SP,並正確插入參數,最後爲第二個SP添加參數,但不要清除第一個調用的參數。它應該是另一個例外 – Steve

+0

另一種選擇:創建一個SP,調用2個當前的SP。那麼你的.NET代碼只需要進行一次數據庫調用。 – Adam

回答

0

三個問題是:

  1. 執行sqlCmd.ExecuteNonQuery()過早 - 這是建立SqlCommand對象後,最後執行的操作,你會怎麼做
  2. 再利用SqlCommand對象爲兩種不同的操作
  3. 沒有包裹在Using聲明SqlCommand對象

編輯:

由於@Andrew莫頓評論說,這可能是因爲你的意思是從一個查詢重新使用參數到下一個查詢,在這種情況下,兩個SqlCommandUsing語句應該合併。

Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles btnBookRepair.Click 
    'Declare variables 
    Dim bookedInBy, deviceType, bookedInDate, fName, lName, address, contactNum, altContactNum, deviceName, accessories, devicePassword, repairType, technicalNotes, repairStatus, completedNotes As String 
    Dim trackingNum As Integer 

    'Setting Date 
    bookedInDate = txtBookedInDate.Text 

    'Assigning variables 
    bookedInBy = DDLBookedInBy.SelectedItem.Text 
    deviceType = DDLDeviceType.SelectedItem.Text 
    trackingNum = txtTrackingNumber.Text 
    fName = txtFname.Text 
    lName = txtLname.Text 
    address = txtAddress.Text 
    contactNum = txtContactNum.Text 
    altContactNum = txtAltContactNum.Text 
    deviceName = txtDeviceName.Text 
    accessories = DDLAccessories.SelectedItem.Text 
    devicePassword = txtDevicePassword.Text 
    repairType = DDLRepairType.SelectedItem.Text 
    technicalNotes = txtTechnical.Text 
    repairStatus = DDLRepairStatus.SelectedItem.Text 
    completedNotes = txtCompletedNotes.Text 

    Dim sqlCS As String 

    sqlCS = ConfigurationManager.ConnectionStrings("Database").ConnectionString 
    Try 
     Using sqlConn As New SqlConnection(sqlCS) 
      sqlConn.Open() 
      Using sqlCmd as New SqlCommand 
       sqlCmd.Connection = sqlConn 
       sqlCmd.CommandText = "InsertToRepair" 
       sqlCmd.CommandType = Data.CommandType.StoredProcedure 

       sqlCmd.Parameters.AddWithValue("@Tracking_Number", trackingNum) 
       sqlCmd.Parameters.AddWithValue("@Booked_in_by", bookedInBy) 
       sqlCmd.Parameters.AddWithValue("@Device_Type", deviceType) 
       sqlCmd.Parameters.AddWithValue("@Booked_In_Date", bookedInDate) 
       sqlCmd.Parameters.AddWithValue("@Device_Name", deviceName) 
       sqlCmd.Parameters.AddWithValue("@Accessories", accessories) 
       sqlCmd.Parameters.AddWithValue("@DevicePassword", devicePassword) 
       sqlCmd.Parameters.AddWithValue("@Repair_Type", repairType) 
       sqlCmd.Parameters.AddWithValue("@Technical_Notes", technicalNotes) 
       sqlCmd.Parameters.AddWithValue("@Completed_Notes", completedNotes) 
       sqlCmd.Parameters.AddWithValue("@RepairStatus", repairStatus) 

       sqlCmd.ExecuteNonQuery() 

      End Using 
      Using sqlCmd as New SqlCommand 
       sqlCmd.Connection = sqlConn 
       sqlCmd.CommandText = "InsertToCustomer" 
       sqlCmd.CommandType = Data.CommandType.StoredProcedure 

       sqlCmd.Parameters.AddWithValue("@First_Name", fName) 
       sqlCmd.Parameters.AddWithValue("@Last_Name", lName) 
       sqlCmd.Parameters.AddWithValue("@ContactNumber", contactNum) 
       sqlCmd.Parameters.AddWithValue("@Alternative_Contact_Number", altContactNum) 
       sqlCmd.Parameters.AddWithValue("@CustomerAddress", address) 

       sqlCmd.ExecuteNonQuery() 
      End Using 
     End Using 

    Catch ex As Exception 
     StatusLabel.Text = ex.ToString 
    End Try 
End Sub 
+0

重新使用SqlCommand不是問題。 –

+0

我同意'SqlCommand'對象_can_可以被重複使用,但不是沒有清除其使用之間的參數集合。簡單地使用另一個對象是最安全的。 – STLDeveloper

+0

這可能是OP希望來自第一個SP的參數在第二個SP中使用。我要求澄清。所呈現的代碼可能比第一次出現時更聰明,更錯誤。 –

0

Steve在評論中指出了一個主要問題:在調用使用它們的命令之前必須添加參數。否則,它就像在你有任何成分之前嘗試烤蛋糕 - 它沒有任何意義。

可能出現的第二個問題是AddWithValue不可靠。 Can we stop using AddWithValue() already?有關於此的信息。

作爲樣式註釋,建議您在變暗時將變量賦值給變量,而不是單獨做兩個變量。 [我現在找不到MSDN頁面。]另外,如果按照使用順序列出變量,如果您將來需要閱讀或調試代碼,則會更容易。

變量trackingNumbookedInDate看起來應該分別是Integer和DateTime,所以您應該明確地製作和使用它們。如果您使用Option Strict On,Visual Studio將有助於指出變量類型的異常。

而不是檢查所有的用戶輸入的有效性(你真的應該這樣做 - 永遠不要相信用戶輸入 - 貓可能已經走過了鍵盤),我將發送到數據庫的代碼作了分解,以便我能夠把它全部放入一個Try ... Catch。

所以,你的代碼可能是這個樣子:

Option Infer On 
Option Strict On 

Imports System.Data.SqlClient 

Public Class Form1 

    Sub SendDataToDB() 

     Dim trackingNum As Integer = CInt(txtTrackingNumber.Text) 
     Dim bookedInDate As DateTime = DateTime.Parse(txtBookedInDate.Text) 

     Dim bookedInBy = DDLBookedInBy.SelectedItem.Text 
     Dim deviceType = DDLDeviceType.SelectedItem.Text 
     Dim deviceName = txtDeviceName.Text 
     Dim accessories = DDLAccessories.SelectedItem.Text 
     Dim devicePassword = txtDevicePassword.Text 
     Dim repairType = DDLRepairType.SelectedItem.Text 
     Dim technicalNotes = txtTechnical.Text 
     Dim completedNotes = txtCompletedNotes.Text 
     Dim repairStatus = DDLRepairStatus.SelectedItem.Text 

     Dim fName = txtFname.Text 
     Dim lName = txtLname.Text 
     Dim contactNum = txtContactNum.Text 
     Dim altContactNum = txtAltContactNum.Text 
     Dim address = txtAddress.Text 

     Dim sqlCS As String = ConfigurationManager.ConnectionStrings("Database").ConnectionString 

     Using sqlConn As New SqlConnection(sqlCS) 
      Using sqlCmd As New SqlCommand() 

       sqlCmd.Connection = sqlConn 
       sqlCmd.CommandType = Data.CommandType.StoredProcedure 

       ' first store the repair data... ' 
       sqlCmd.CommandText = "InsertToRepair" 

       sqlCmd.Parameters.Add(New SqlParameter With {.ParameterName = "@Tracking_Number", .SqlDbType = SqlDbType.Int, .Value = trackingNum}) 
       sqlCmd.Parameters.Add(New SqlParameter With {.ParameterName = "@Booked_In_Date", .SqlDbType = SqlDbType.DateTime, .Value = bookedInDate}) 
       'TODO: Set the .Size to be the same as the declaration in the database. ' 
       sqlCmd.Parameters.Add(New SqlParameter With {.ParameterName = "@Booked_in_by", .SqlDbType = SqlDbType.NVarChar, .Size = 100, .Value = bookedInBy}) 
       'TODO: Convert the following AddWithValue to Add as above. ' 
       sqlCmd.Parameters.AddWithValue("@Device_Type", deviceType) 
       sqlCmd.Parameters.AddWithValue("@Device_Name", deviceName) 
       sqlCmd.Parameters.AddWithValue("@Accessories", accessories) 
       sqlCmd.Parameters.AddWithValue("@DevicePassword", devicePassword) 
       sqlCmd.Parameters.AddWithValue("@Repair_Type", repairType) 
       sqlCmd.Parameters.AddWithValue("@Technical_Notes", technicalNotes) 
       sqlCmd.Parameters.AddWithValue("@Completed_Notes", completedNotes) 
       sqlCmd.Parameters.AddWithValue("@RepairStatus", repairStatus) 

       sqlConn.Open() 
       sqlCmd.ExecuteNonQuery() 

       ' now store the customer data, with additional parameters... ' 
       sqlCmd.CommandText = "InsertToCustomer" 

       'TODO: Use Add instead of AddWithValue. ' 
       sqlCmd.Parameters.AddWithValue("@First_Name", fName) 
       sqlCmd.Parameters.AddWithValue("@Last_Name", lName) 
       sqlCmd.Parameters.AddWithValue("@ContactNumber", contactNum) 
       sqlCmd.Parameters.AddWithValue("@Alternative_Contact_Number", altContactNum) 
       sqlCmd.Parameters.AddWithValue("@CustomerAddress", address) 

       sqlCmd.ExecuteNonQuery() 
       sqlConn.Close() 

      End Using 

     End Using 

    End Sub 

    'TODO: Give Button1 a meaningful name. ' 
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     Try 
      SendDataToDB() 
     Catch ex As Exception 
      StatusLabel.Text = ex.ToString 
     End Try 

    End Sub 

End Class 

(雖然我使用選項推斷對了,我明確地鍵入的前兩個變量爲重點給讀者。)

從有關與SQL參數的工作本網站的過時文件部分:

  • SQL參數的類型和大小不匹配是插入的常見原因/更新/選擇失敗
  • 給你的SQL參數有意義名稱就像您在代碼中執行變量一樣
  • 指定您正在使用的列的數據庫數據類型,這可確保不使用錯誤的參數類型,這可能會導致意外的結果
  • 驗證傳入參數傳遞給命令之前(正如俗話說的,「垃圾進入,垃​​圾出來」)。在堆棧中儘早驗證傳入值
  • 分配參數值時請使用正確的類型,例如:不要分配DateTime的字符串值,而應將實際的DateTime實例分配給參數的值
  • 指定字符串類型參數的大小。這是因爲如果參數匹配的類型和大小SQL Server可以重新使用執行計劃。使用-1作爲MAX
  • 不要使用AddWithValue方法,主要原因是很容易忘記在需要時指定參數類型或精度/縮放比例。

P.S.像「Device_Type」和「RepairStatus」這樣的名稱是不一致的 - 如果您選擇一個命名約定並堅持使用它,則更容易;否則,您將嘗試使用「DeviceType」和「Repair_Status」,並想知道它們爲什麼不起作用。