【问题标题】:Possible to have multiple SqlCommand?可能有多个SqlCommand?
【发布时间】:2012-01-17 17:17:37
【问题描述】:
Dim conn As New SqlConnection("Database=Clinic_Management_System;Data Source=.\SQLExpress;Integrated Security=True;AttachDBFilename=|DataDirectory|Clinic Management System.mdf")
Dim cmd As SqlCommand
Dim dr As SqlDataReader
conn.Open()
cmd = New SqlCommand("INSERT INTO record([PatientID],[Prescription],[VisitDate]) Values ('" & PatientIDTextBox.Text & "','" & txtPrescription.Text & "',GetDate()) ", conn)
cmd.ExecuteNonQuery()

For cn As Integer = 0 To DataGridView1.RowCount - 1
    cmd = New SqlCommand("INSERT INTO record_item([RecordID],[ItemID],[Amount]) Values ( (SELECT MAX(RecordID) FROM record)," & DataGridView1.Rows(cn).Cells(0).Value & "," & DataGridView1.Rows(cn).Cells(2).Value & ")", conn)
    cmd.ExecuteNonQuery()

Next
conn.Close()

这可以同时运行 2 个SqlCommand 吗??

因为在以某种方式执行后,循环内的第二个没有执行或插入数据。

【问题讨论】:

  • 您遇到错误了吗?你试过调试吗?第二个cmd.ExecuteNonQuery会发生什么?
  • 没有错误,调试后尝试插入一些数据,但是数据库仍然是空的,只有第一个 sqlcommand 工作
  • 你的 DataGrid 有行吗?
  • 是的...现在我怀疑命令可能不正确

标签: sql vb.net sqlcommand


【解决方案1】:

您没有 2 个 SqlCommand。

您有 1 个 SqlCommand,名为 cmd,它被执行了多次。

这样做很好,但是我会为您的INSERT INTO record 设置 1 个 SqlCommand,为您的INSERT INTO record_item 设置 1 个。我认为这使得以后回顾代码时更容易理解。

无论哪种方式,使用这样的 SqlCommand 不应阻止它执行,因此我相信您的脚本还有另一个问题。


我已经修改了您的代码,以便将其拆分为 2 个单独的 SqlCommand 对象,并且查询已被参数化以防止 SQL 注入:

Dim conn As New SqlConnection("Database=Clinic_Management_System;Data Source=.\SQLExpress;Integrated Security=True;AttachDBFilename=|DataDirectory|Clinic Management System.mdf")

Dim cmdRecord As New SqlCommand("INSERT INTO record ([PatientID],[Prescription],[VisitDate]) Values (@PatientID, @Prescription, GETDATE())", conn)
cmdRecord.Parameters.Add("@PatientID", SqlDbType.Int).Value = PatientIDTextBox.Text
cmdRecord.Parameters.Add("@Prescription", SqlDbType.NVarChar).Value = txtPrescription.Text

Dim cmdRecordItem As New SqlCommand("INSERT INTO record_item([RecordID],[ItemID],[Amount]) Values ( (SELECT MAX(RecordID) FROM record),@ItemID,@AmountID)", conn)
cmdRecordItem.Parameters.Add("@ItemID", SqlDbType.Int)
cmdRecordItem.Parameters.Add("@Amount", SqlDbType.Decimal)

Dim dr As SqlDataReader
conn.Open()

cmdRecord.ExecuteNonQuery()

For cn As Integer = 0 To DataGridView1.RowCount - 1
    cmdRecordItem.Parameters("@ItemID").Value = DataGridView1.Rows(cn).Cells(0).Value
    cmdRecordItem.Parameters("@Amount").Value = DataGridView1.Rows(cn).Cells(2).Value

    cmdRecordItem.ExecuteNonQuery()

Next
conn.Close()

【讨论】:

  • OP只有一个SqlCommand变量,但实际上创建了多个SqlCommand对象。有两个新的 SqlCommand() 赋值,一个在循环中。
  • 这是真的,但新的 SqlCommand 对象也可能只是对 CommandText 的更改,因为其他一切都保持不变。
  • 是的,绝对......但你的回答说他只有一个 SqlCommand。
  • 感谢代码,我才意识到,问题是 Dim cmdRecordItem As New SqlCommand("INSERT INTO record_item([RecordID],[ItemID],[Amount]) Values ( (SELECT MAX(RecordID ) FROM record),@ItemID,@AmountID)", conn) 即使我为这 3 个项目设置了默认值,该值也无法存储在数据库中,不知道为什么...我检查了名称,列名都正确
【解决方案2】:

一个命令只能使用一次。 如果要使用多个命令,请将新的cmd 声明为

Dim cmd2 as SqlCommand

【讨论】:

    【解决方案3】:

    为了确保所有语句都成功完成或没有一个成功完成,您需要将命令包装在事务中。

    对命令使用参数也会使代码更易于理解和更安全,您应该尽可能使用 using 语句。

    另外,执行 Select max recordid 是一个非常糟糕的主意(如果您有多个用户),但我将把它留到另一个时间:

        Using conn As New SqlConnection("Database=Clinic_Management_System;Data Source=.\SQLExpress;Integrated Security=True;AttachDBFilename=|DataDirectory|Clinic Management System.mdf")
            Dim cmdRecord As SqlCommand
            Dim cmdRecordItem As SqlCommand
            Dim oTran As SqlTransaction = Nothing
    
            conn.Open()
            Try
                cmdRecord = New SqlCommand("INSERT INTO record([PatientID],[Prescription],[VisitDate]) Values (@PatientID, @Prescription, GetDate())", conn)
                cmdRecord.Parameters.AddWithValue("@PatientID", PatientIDTextBox.Text)
                cmdRecord.Parameters.AddWithValue("@Prescription", txtPrescription.Text)
    
                cmdRecordItem = New SqlCommand("INSERT INTO record_item([RecordID],[ItemID],[Amount]) SELECT ISNULL(MAX(RecordID), 0), @ItemID, @Amount FROM record", conn)
                cmdRecordItem.Parameters.Add("@ItemId")
                cmdRecordItem.Parameters.Add("@Amount")
    
                oTran = conn.BeginTransaction
    
                cmdRecord.ExecuteNonQuery()
    
                For Each oRow As DataGridViewRow In DataGridView1
                    cmdRecordItem.Parameters("@ItemId").Value = oRow.Cells(0).Value
                    cmdRecordItem.Parameters("@Amount").Value = oRow.Cells(2).Value
    
                    cmdRecordItem.ExecuteNonQuery()
                Next
    
                oTran.Commit()
            Catch
                If oTran IsNot Nothing Then
                    oTran.Rollback()
                End If
    
                Throw
            Finally
                conn.Close()
            End Try
        End Using
    

    【讨论】:

    • 这段代码不知何故也不能正常工作,就像你说的那样,要么全部完成,要么没有
    • @user1151874:是否有任何异常被抛出?我已经更新了插入记录项以使用不同的查询格式,以防出现问题。
    猜你喜欢
    • 2013-12-13
    • 1970-01-01
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 2016-02-04
    • 1970-01-01
    相关资源
    最近更新 更多