【问题标题】:How to loop SQL command through set of textboxes如何通过一组文本框循环 SQL 命令
【发布时间】:2020-10-08 02:12:34
【问题描述】:

我在一个 flowlayoutpanel 中有一组三个面板。 Panel1 包含名为 title1、city1、state1 等的文本框控件。 panel2 控件将分别命名为 title2、city2、state2,panel3 也是如此。

我的目标是从每个面板中的所有文本框中收集所有 .text 属性,并使用 INSERT 命令将它们存储在数据库中。

我的代码如下所示:

Dim i As Integer = 1

Do
    connection.Open()

    cmd = New SqlCommand(Insert, connection)
    cmd.Parameters.AddWithValue("@user_id", My.Settings.CurrentUserID)
    cmd.Parameters.AddWithValue("@title", ("title" + i.ToString))
    cmd.Parameters.AddWithValue("@job_status", " ")
    cmd.Parameters.AddWithValue("@jobnumber", i)
    cmd.Parameters.AddWithValue("@employer", ("employer" + i.ToString))
    cmd.Parameters.AddWithValue("@city", ("city" + i.ToString))
    cmd.Parameters.AddWithValue("@state", ("state" + i.ToString))
    cmd.Parameters.AddWithValue("@startdate", ("startdate" + i.ToString))
    cmd.Parameters.AddWithValue("@enddate", ("enddate" + i.ToString))
    cmd.Parameters.AddWithValue("@jobinfo", ("jobinfo" + i.ToString))
    cmd.ExecuteNonQuery()

    i = i + 1
    connection.Close()
Loop Until i = 4

这个循环工作正常,在表中插入 3 行值,但它实际上插入的是字符串(title1,title2),而不是名为 textbox 的字符串的 .Text 属性

我尝试寻找将字符串转换为控件名称的方法,但找不到任何适合我的方法

或者,我尝试这样做:

cmd.Parameters.AddWithValue("@title", ("title" + i.ToString).text)

但它给了我这个错误:

“文本”不是成员“字符串”

通过执行一堆 If 语句并为每个文本框名称手动编写代码,很难实现我的目标,但现在,我正尽可能有效地做到这一点。

期待您的建议!

编辑:按照@JoelCoehoorn 解决方案,我能够解决我的问题

cmd = New SqlCommand(Insert, connection)

cmd.Parameters.Add("@user_id", SqlDbType.Int).Value = My.Settings.CurrentUserID
cmd.Parameters.Add("@title", SqlDbType.VarChar, 100)
cmd.Parameters.Add("@job_status", SqlDbType.VarChar, 20).Value = " "
cmd.Parameters.Add("@jobnumber", SqlDbType.Int)
cmd.Parameters.Add("@employer", SqlDbType.VarChar, 100)
cmd.Parameters.Add("@city", SqlDbType.VarChar, 100)
cmd.Parameters.Add("@state", SqlDbType.Char, 100)
cmd.Parameters.Add("@startdate", SqlDbType.VarChar, 20)
cmd.Parameters.Add("@enddate", SqlDbType.VarChar, 20)
cmd.Parameters.Add("@jobinfo", SqlDbType.VarChar, 1000)

connection.Open()

For i As Integer = 1 To 3
    Dim pnl As System.Windows.Forms.Panel = CType(FlowLayoutPanel2.Controls($"WorkPanel{i}"), Control)
    Dim targetBox As TextBox
    Dim datepicker As DateTimePicker

    targetBox = CType(pnl.Controls($"title{i}"), Control)
    cmd.Parameters("@title").Value = targetBox.Text

    cmd.Parameters("@jobnumber").Value = i

    targetBox = CType(pnl.Controls($"employer{i}"), Control)
    cmd.Parameters("@employer").Value = targetBox.Text

    targetBox = CType(pnl.Controls($"city{i}"), Control)
    cmd.Parameters("@city").Value = targetBox.Text

    targetBox = CType(pnl.Controls($"state{i}"), Control)
    cmd.Parameters("@state").Value = targetBox.Text

    datepicker = CType(pnl.Controls($"startdate{i}"), Control)
    cmd.Parameters("@startdate").Value = datepicker.Value

    datepicker = CType(pnl.Controls($"enddate{i}"), Control)
    cmd.Parameters("@enddate").Value = datepicker.Value

    targetBox = CType(pnl.Controls($"jobinfo{i}"), Control)
    cmd.Parameters("@jobinfo").Value = targetBox.Text

    cmd.ExecuteNonQuery()
Next

【问题讨论】:

  • 您需要将控件分配给三个控件数组,然后您可以使用索引器遍历这些数组。 Hans Passant 对this question 的回答应该会为您指明正确的方向。
  • @JonathanWillcock,感谢您的评论!我知道可以创建一个控件数组,但是如果使用数组,我仍然对如何索引每个文本框感到困惑。

标签: vb.net visual-studio


【解决方案1】:

我们可以在这里做很多事情。有关说明,请参阅 cmets。

'Thanks to connection pooling, you should think about 
' creating a new connection object for each operation. Really. 
Using connection As New SqlConnection("connection string here"), _
      cmd As New SqlCommand(Insert, connection)

    'Avoid AddWithValue. It has to guess at types, and when (not if) it guesses
    ' wrong it causes index mismatches, which can create severe performance issues.
    'Instead, tell the computer what database types you expect.
    'I have to guess for this answer, but you can replace with exact types from the DB
    cmd.Parameters.Add("@user_id", SqlDbType.Int).Value = My.Settings.CurrentUserID
    cmd.Parameters.Add("@title", SqlDbType.NVarChar, 40)
    cmd.Parameters.Add("@job_status", SqlDbType.VarChar, 10).Value =  " "
    cmd.Parameters.Add("@jobnumber", SqlDbType.Int)
    cmd.Parameters.Add("@employer", SqlDbtype.NVarChar, 80)
    cmd.Parameters.Add("@city", SqlDbtype.NVarChar, 80)
    cmd.Parameters.Add("@state", SqlDbType.Char, 6)
    cmd.Parameters.Add("@startdate", SqlDbType.DateTime)
    cmd.Parameters.Add("@enddate", SqlDbType.DateTime)
    cmd.Parameters.Add("@jobinfo", SqDbType.NVarChar, 120)

    'A tight loop like this is the rare exception to creating new connections.
    ' In this situation, open the connection once before the loop, close it after
    connection.Open()
    For i As Integer = 1 To 3
        'Inside the loop, we only need to update values for parameters that change

        'Use the "Find()" function in Winforms to search for a control by name
        'String interpolation can help build the names
        Dim pnl As Panel = FlowLayoutPanel1.Controls.Find($"Panel{i}")
        Dim target As Control

        target = pnl.Controls.Find($"title{i}", True)
        cmd.Parameters("@title").Value = target.Text
        cmd.Parameters("@jobnumber").Value = i
        target = pnl.Controls.Find($"employer{i}", True)
        cmd.Parameters("@employer").Value = target.Text
        target = pnlControls.Find($"city{i}", True)
        cmd.Parameters("@city").Value = target.Text
        target = pnl.Controls.Find($"state{i}", True)
        cmd.Parameters("@state").Value = target.Text
        target = pnl.Controls.Find($"startdate{i}", True)
        cmd.Parameters("@startdate").Value = DateTime.Parse(target.Text)
        target = pnl.Controls.Find($"enddate{i}", True)
        cmd.Parameters("@enddate").Value = DateTime.Parse(target.Text)
        target = pnl.Controls.Find($"jobinfo{i}", True)
        cmd.Parameters("@jobinfo").Value = target.Text

        cmd.ExecuteNonQuery()
    Next

'The Using block is a MUCH safer way to call connection.Close()
' It ensures the connection still closes if an exception is thrown
End Using

再深入一点,对于这种情况,我将基于带有文本框的面板创建一个新控件,自定义控件或用户控件。然后把这个新的控件类型放到 FlowLayoutPanel 中。该控件还将具有每个文本框字段的属性。这样,您只需执行一次Find() 步骤。

【讨论】:

  • 感谢这段代码和非常详细的解释!我会尝试在我的代码中实现它,如果它有效,我会告诉你!
  • 您的解决方案很有魅力!不得不调试一些东西并实现 CType() 而不是 Find() 函数,因为我无法让它正常工作。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-02
  • 2022-10-24
  • 2015-09-14
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多