For 循环继续 For

时间:2021-02-03 14:22:20

标签: vb.net

我正在尝试过滤列表视图中列出的项目。应该检查列表视图上的每个项目是否已经存在于我的数据库中。而那些不在数据库中的,将被插入。

这是我试过的代码。

Sub Save()
    For Each item As ListViewItem In ListViewSelectedOffice.Items
        CONNECTION.Close()
        CONNECTION.Open()
        Query = "SELECT * FROM table_documentdestinationlog WHERE LogNo = '" & Me.TextBoxLogNo.Text & "' AND OfficeDestination = '" & item.SubItems(1).Text & "'"
        comm = New MySqlCommand(Query, CONNECTION)
        Reader = comm.ExecuteReader
        If Reader.HasRows = True Then
            Continue For
        End If
        'Do Something
        CONNECTION.Close()
        CONNECTION.Open()
        Query = "INSERT INTO table_documentdestinationlog (LogNo, OfficeDestination, Status) VALUES (@logno, @officeD, 'Pending')"
        comm = New MySqlCommand(Query.ToString, CONNECTION)
        comm.Parameters.AddWithValue("@logno", LabelLogNo.Text)
        comm.Parameters.AddWithValue("@officeD", item.SubItems(1).Text)
        comm.ExecuteNonQuery()
    Next item

我也试过

 Sub SaveToDestinationLog1()
        For Each item As ListViewItem In ListViewSelectedOffice.Items
            CONNECTION.Close()
            CONNECTION.Open()
            Query = "SELECT * FROM table_documentdestinationlog WHERE LogNo = '" & Me.TextBoxLogNo.Text & "' AND OfficeDestination = '" & item.SubItems(1).Text & "'"
            comm = New MySqlCommand(Query, CONNECTION)
            Reader = comm.ExecuteReader
            If Reader.HasRows = True Then
                Continue For

            Else
                GoTo LINE1
            End If

LINE1:
            'Do Something
            CONNECTION.Close()
            CONNECTION.Open()
            Query = "INSERT INTO table_documentdestinationlog (LogNo, OfficeDestination, Status) VALUES (@logno, @officeD, 'Pending')"
            comm = New MySqlCommand(Query.ToString, CONNECTION)
            comm.Parameters.AddWithValue("@logno", LabelLogNo.Text)
            comm.Parameters.AddWithValue("@officeD", item.SubItems(1).Text)
            comm.ExecuteNonQuery()
        Next item
    End Sub

还是没有得到我想要的结果。

3 个答案:

答案 0 :(得分:0)

当逻辑变得难以遵循并且执行“需要”开始上下跳跃时,是时候稍微重组一下了。

将代码提取为更小、更专业的函数,使您的 Save 过程更清晰:

Private Sub Save()
    Dim LogID As String = Me.TextBoxLogNo.Text
    For Each item As ListViewItem In ListViewSelectedOffice.Items
        Dim OfficeDest As String = item.SubItems(1).Text
        If IsNewEntry(LogID, OfficeDest) Then
            InsertNewPendingEntry(LogID, OfficeDest)
        End If
    Next
End Sub

现在,您需要一个 IsNewEntry 函数,该函数在应插入条目时返回 True,如果条目已存在,则返回 False。为什么你在这里将用户输入连接到 WHERE 子句中?这会创建一个不必要的 SQL injection vulnerability,您可以在几行之后使用形式参数安全地避免它:在任何地方都这样做!

然后您需要一个实际执行插入操作的 InsertNewPendingEntry 方法 - 这就是您在 LINE1: 标签下的内容。

考虑使连接本地连接到 Save 方法(并将其作为参数传递给 IsNewEntryInsertNewPendingEntry 方法),包含在 Using 块中以确保正确处理;当您正确处理连接时,无需显式 Close 连接。我的经验法则是,如果我不知道下一个命令何时会触发连接,那么我需要处理该连接。在 .NET 中,任何实现 IDisposable 应该的类型都应该调用它的 Dispose 方法,最简单的方法是利用 Using 块。

Try/Catch 块也是有保证的,因为数据库连接可能会出现许多您无法控制的错误。

答案 1 :(得分:0)

这里的技巧是使用 Insert Into...Where Not Exists。数据库对象需要在使用它们的方法中声明、关闭和处置。即使出现错误,Using...End Using 块也会为我们处理这个问题。

For 循环中唯一改变的是 @officeD 参数的值。所以,那个和 .Execute 是唯一属于循环的东西。我们不需要重新创建连接或命令。我们不想随意打开和关闭连接。

Sub Save()
    Dim Query = "INSERT INTO table_documentdestinationlog (LogNo, OfficeDestination, Status) VALUES (@logno, @officeD, 'Pending') 
                    Where Not Exists(SELECT * FROM table_documentdestinationlog WHERE LogNo = @logno AND OfficeDestination = @officeD)"
    Using CONNECTION As New MySqlConnection(ConStr),
            comm As New MySqlCommand(Query, CONNECTION)
        comm.Parameters.Add("@logno", MySqlDbType.VarChar).Value = LabelLogNo.Text
        comm.Parameters.Add("@officeD", MySqlDbType.VarChar)
        CONNECTION.Open()
        For Each item As ListViewItem In ListViewSelectedOffice.Items
            comm.Parameters("@officeD").Value = item.SubItems(1).Text
            comm.ExecuteNonQuery()
        Next
    End Using
End Sub

答案 2 :(得分:0)

抱歉给麻烦的人。但这段代码确实有效。我只是没有注意到 WHERE 子句的值是错误的。我没有注意到我在 WHERE 子句中使用了 TextBoxLogNo.text 而不是 LabelLogno.text。这就是为什么它没有为 reader.hasrows 返回正确的值。我为每次迭代都放置了 msgbox,并注意到它确实没有返回我想要的值。所以我查看了我的查询和 WHERE 子句。当然,您的所有建议都非常有帮助。

Sub Save()
    For Each item As ListViewItem In ListViewSelectedOffice.Items
        CONNECTION.Close()
        CONNECTION.Open()
        Query = "SELECT * FROM table_documentdestinationlog WHERE LogNo = '" & Me.TextBoxLogNo.Text & "' AND OfficeDestination = '" & item.SubItems(1).Text & "'"
        comm = New MySqlCommand(Query, CONNECTION)
        Reader = comm.ExecuteReader
        If Reader.HasRows = True Then
            Continue For
        End If
        'Do Something
        CONNECTION.Close()
        CONNECTION.Open()
        Query = "INSERT INTO table_documentdestinationlog (LogNo, OfficeDestination, Status) VALUES (@logno, @officeD, 'Pending')"
        comm = New MySqlCommand(Query.ToString, CONNECTION)
        comm.Parameters.AddWithValue("@logno", LabelLogNo.Text)
        comm.Parameters.AddWithValue("@officeD", item.SubItems(1).Text)
        comm.ExecuteNonQuery()
    Next item