You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET一键执行多条Insert查询的问题及解决方法求助

问题分析与解决方案

核心问题

  1. OleDbCommand参数未清空:重复使用同一个cmd对象执行不同SQL时,之前添加的参数会保留在集合中,导致后续SQL执行时参数数量/名称不匹配,出现"参数无默认值"或数据串入其他表的问题。
  2. 重复定义saveorder方法:代码中存在两个完全相同的saveorder方法,会引发编译逻辑错误。
  3. invoice_id获取方式错误:插入invoice后未获取数据库自动生成的主键ID,直接使用输入框值可能为空或无效,导致invoice_items插入失败。
  4. 连接管理不规范:频繁关闭/打开数据库连接,且未使用Using语句自动释放资源,容易引发连接泄漏。

修复步骤

  • 为每个SQL操作创建新的OleDbCommand对象(或每次执行前清空参数集合),避免参数累积。
  • 删除重复的saveorder方法,保留一个实现。
  • 插入invoice后,使用SELECT SCOPE_IDENTITY()获取自动生成的invoice_id,用于后续invoice_items插入。
  • 使用Using语句管理OleDbConnection和OleDbCommand,确保资源自动释放,无需手动频繁开关连接。

修复后的代码示例

Private Sub add_Click(sender As Object, e As EventArgs) Handles add.Click
    If String.IsNullOrEmpty(client_name.Text) Or String.IsNullOrEmpty(company_name.Text) Or 
       String.IsNullOrEmpty(email.Text) Or String.IsNullOrEmpty(contact_no.Text) Or 
       String.IsNullOrEmpty(address.Text) Or String.IsNullOrEmpty(delivery_address.Text) Then
        MessageBox.Show("请填写所有字段", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
    Else
        If issaved = 1 Then
            MessageBox.Show("费用已保存", "保存提示", MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else
            saveorder()
            issaved = 1
        End If
    End If
End Sub

Public Sub saveorder()
    Dim debit As Int64 = Convert.ToInt64(total_basic_amount.Text) + Convert.ToInt64(freigh_rate.Text) + Convert.ToInt64(delivery_rate.Text)
    Dim invoiceId As Integer = 0

    ' 使用Using管理连接,自动释放资源
    Using cn As New OleDbConnection("你的数据库连接字符串")
        cn.Open()

        ' 插入ledger借方记录
        Using cmd As New OleDbCommand("insert into ledger([client_name],[registration_no],[company_name],[date],[credit],[debit])Values(@client_name,@registration_no,@company_name,@date,@credit,@debit)", cn)
            cmd.Parameters.AddWithValue("@client_name", client_name.Text)
            cmd.Parameters.AddWithValue("@registration_no", reg_no.Text)
            cmd.Parameters.AddWithValue("@company_name", company_name.Text)
            cmd.Parameters.AddWithValue("@date", datetime.Value.ToShortDateString)
            cmd.Parameters.AddWithValue("@credit", 0)
            cmd.Parameters.AddWithValue("@debit", debit)
            cmd.ExecuteNonQuery()
        End Using
        MessageBox.Show("ledger借方记录已存储")

        ' 插入ledger贷方记录
        Using cmd As New OleDbCommand("insert into ledger([client_name],[registration_no],[company_name],[date],[credit],[debit])Values(@client_name,@registration_no,@company_name,@date,@credit,@debit)", cn)
            cmd.Parameters.AddWithValue("@client_name", client_name.Text)
            cmd.Parameters.AddWithValue("@registration_no", reg_no.Text)
            cmd.Parameters.AddWithValue("@company_name", company_name.Text)
            cmd.Parameters.AddWithValue("@date", datetime.Value.ToShortDateString)
            cmd.Parameters.AddWithValue("@credit", Convert.ToInt64(advance_received_amount.Text))
            cmd.Parameters.AddWithValue("@debit", 0)
            cmd.ExecuteNonQuery()
        End Using
        MessageBox.Show("ledger贷方记录已存储")

        ' 插入invoice并获取自动生成的ID
        Using cmd As New OleDbCommand("insert into invoice([invoice_date],[client_name],[client_company_name],[client_email],[client_contact_no],[client_address],[client_delivery_address],[total_basic_amount],[freight_rate],[delivery_rate],[advanced_amount],[pending_amount]) values(@invoice_date,@client_name,@client_company_name,@client_email,@client_contact_no,@client_address,@client_delivery_address,@total_basic_amount,@freight_rate,@delivery_rate,@advanced_amount,@pending_amount); SELECT SCOPE_IDENTITY();", cn)
            cmd.Parameters.AddWithValue("@invoice_date", datetime.Value.ToShortDateString)
            cmd.Parameters.AddWithValue("@client_name", client_name.Text)
            cmd.Parameters.AddWithValue("@client_company_name", company_name.Text)
            cmd.Parameters.AddWithValue("@client_email", email.Text)
            cmd.Parameters.AddWithValue("@client_contact_no", contact_no.Text)
            cmd.Parameters.AddWithValue("@client_address", address.Text)
            cmd.Parameters.AddWithValue("@client_delivery_address", delivery_address.Text)
            cmd.Parameters.AddWithValue("@total_basic_amount", total_basic_amount.Text)
            cmd.Parameters.AddWithValue("@freight_rate", freigh_rate.Text)
            cmd.Parameters.AddWithValue("@delivery_rate", delivery_rate.Text)
            cmd.Parameters.AddWithValue("@advanced_amount", advance_received_amount.Text)
            cmd.Parameters.AddWithValue("@pending_amount", total_pending_amount.Text)
            ' 获取插入后的invoice_id
            invoiceId = Convert.ToInt32(cmd.ExecuteScalar())
        End Using
        MessageBox.Show("invoice已存储")

        ' 插入invoice_items(排除DataGridView最后一行空行)
        For i As Integer = 0 To DataGridView1.Rows.Count - 2
            Using cmd As New OleDbCommand("insert into invoice_items([invoice_id],[item_name],[qty],[rate])Values(@invoice_id,@item_name,@qty,@rate)", cn)
                cmd.Parameters.AddWithValue("@invoice_id", invoiceId)
                cmd.Parameters.AddWithValue("@item_name", DataGridView1.Rows(i).Cells(2).Value)
                cmd.Parameters.AddWithValue("@qty", DataGridView1.Rows(i).Cells(3).Value)
                cmd.Parameters.AddWithValue("@rate", DataGridView1.Rows(i).Cells(4).Value)
                cmd.ExecuteNonQuery()
            End Using
        Next
        MessageBox.Show("发票明细已存储")
    End Using
End Sub

额外优化建议

  • 不要直接用Convert.ToInt64转换文本框内容,添加输入验证(比如用Int64.TryParse),避免输入非数字时抛出异常。
  • 数据库表字段类型要和代码中传入的参数类型匹配(比如日期字段直接传入DateTime类型,而非转换为字符串)。
  • 所有数据库操作建议包裹在Try-Catch块中,捕获并处理异常,避免程序崩溃。

内容的提问来源于stack exchange,提问作者John MacClain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 02:15:44