我正在尝试过滤列表视图中列出的项目。应该检查列表视图上的每个项目是否已经存在于我的数据库中。而那些不在数据库中的,将被插入。
这是我试过的代码。
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
还是没有得到我想要的结果。
答案 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
方法(并将其作为参数传递给 IsNewEntry
和 InsertNewPendingEntry
方法),包含在 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