【问题标题】:Looping through SqlDataReader returns same row twice循环遍历 SqlDataReader 两次返回同一行
【发布时间】:2016-04-29 18:35:05
【问题描述】:

我正在制作一个 VB.NET (4.6) Windows 窗体应用程序,它收集我们服务器上的信息并允许我们对其进行报告。它很好地结合在一起,但我遇到了一个我无法弄清楚的问题。该项目的一部分是一项服务,该服务从 WSUS 查询有关可用 Windows 更新的信息,然后将它们存储在 SQL 数据库中——该部分工作正常。我现在尝试使用 SqlDataReader 在 DataGridView 中显示这些数据,以从数据库中查询信息并用响应填充 DataTable。问题是当我使用阅读器时,它会将相同的记录放入 DataTable 中两次。我不确定我做错了什么,而且我敢肯定这是非常简单的事情。也许你们中的一个人可以发现问题?

注意:在应用程序的早期,updateid 以唯一字符串的形式存储在名为 dbupdateidlist 的列表中,结果存储在名为 dbupTable 的 DataTable 中,而我尝试更新的 datagridview 名为 UpdateDeetsView。

Public Sub getUpdateDetails()

    For Each str As String In dbupdateidlist
        Dim commGetUpdateDetails As String = "select upTableId, title, classification, description, " +
        "releasedate, severity, articlenumber, url from updatedetails where updateid = '" + str + "'"
        Using connObj As New SqlClient.SqlConnection(connectionString)
            Using cmdObj As New SqlClient.SqlCommand(commGetUpdateDetails, connObj)
                connObj.Open()
                Using readerObj As SqlClient.SqlDataReader = cmdObj.ExecuteReader
                    While readerObj.Read

                        dbuptabid = readerObj("uptableid")
                        dbuptitle = readerObj("title")
                        dbupclass = readerObj("classification")
                        dbupdesc = readerObj("description")
                        dbupreleasedate = readerObj("releasedate")
                        dbupseverity = readerObj("severity")
                        dbuparticlenumber = readerObj("articlenumber")
                        dbupurl = readerObj("url")

                        row = dbupTable.NewRow()
                        row("uptableid") = dbuptabid
                        row("title") = dbuptitle
                        row("classification") = dbupclass
                        row("description") = dbupdesc
                        row("releasedate") = dbupreleasedate
                        row("severity") = dbupseverity
                        row("articlenumber") = dbuparticlenumber
                        row("url") = dbupurl
                        dbupTable.Rows.Add(row)
                    End While

                End Using
                connObj.Close()
            End Using
        End Using
    Next
    UpdateDeetsView.DataSource = dbupTable
End Sub

请原谅可能很糟糕的代码,我是 SA 而不是开发人员...

【问题讨论】:

  • 无需将行一一移动到数据表中。 dbupTable.Load(readerObj.ExecuteReader) 将为您填写表格。如果您在其他地方有该表,则可以只使用它的 DataView。但无论如何,打开 Option Strict
  • 即使只是一个 SA,也要始终使用参数来避免 SQL 注入和格式问题。
  • dbupdateidlist 是否包含重复值?
  • 这不是sql-server问题,请正确使用标签。
  • @Plutonix 感谢您的提示!但是,我用 dbupTable.Load(cmdObj.ExecuteReader) 替换了整个 While 循环,它仍然显示两个结果。 Option Strict 能为我做什么?

标签: vb.net sqldatareader


【解决方案1】:

试试这个:

Public Sub getUpdateDetails()
    Dim sql As String = _    
        "SELECT DISTINCT upTableId, title, classification, description, releasedate, " & _
            " severity, articlenumber, url " & _
       " FROM updatedetails " & _ 
       " WHERE updateid = @updateID"

    Using cn  As New SqlClient.SqlConnection(connectionString), _
          cmd As New SqlClient.SqlCommand(sql, cn)

        cmd.Parameters.Add("@updateID", SqlDbType.Int).Value = Int32.Parse(dbupdateidlist.First())
        cn.Open()
        UpdateDeetsView.DataSource = cmd.ExecuteReader()
    End Using
End Sub

请注意 DISTINCT 的使用以及完全没有任何显式循环。

另外请注意,我只查看dbupdateidlist 中的一个条目。您的旧错误的真正来源可能是该列表中的 ID 两次。

【讨论】:

  • 非常感谢!这行得通,突然只得到一排。
  • @user1806800 与您的说法“我已经在 SMSS 中运行它并且我得到了一个结果”相矛盾
  • @Paparazzi 我认为最初的问题是 ID 值在 dbupdateidlist 列表中出现了两次。因此它运行了两次 sql 语句而没有清除其间的数据表。
  • @JoelCoehoorn 我要求 OP 在 SSMS 中进行测试,并且 OP 向我评论返回了 1 行
  • @Paparazzi 没错。请注意问题中的这一行:For Each str As String In dbupdateidlistdbupdateidlist 中有两个值。所以每一行都由查询返回一次,但查询运行了两次。因此,我的答案中真正的解决方法是使用.First() 仅获取一个条目,或者直接分配给数据源,这将清除任何先前运行的项目。
【解决方案2】:

没有方式 readerObj.Read 无法移动到下一条记录

得到这个的输出并运行它是 SSMS

"select upTableId, title, classification, description, " +  
"releasedate, severity, articlenumber, url from updatedetails where updateid = '" + str + "'"

【讨论】:

  • 你可能误解了我的问题,当只有一个存在时它返回两行。我已经在 SMSS 中运行它,我得到了一个结果,但如果它由阅读器运行,我在 DataGridView 中得到相同的行两次。
  • @user1806800 该图像不能证明循环返回两行。在调试模式下跟踪它,如果查询返回一行,它不会循环两次。敲,敲——如果你叫它两次,你就会得到结果。
  • @user1806800 我会仔细检查只存在一行的假设
  • 敲,敲。您声明“通过 SqlDataReader 循环返回同一行两次”。那是错误的。 loop 不会两次返回同一行。如果它被调用了两次,那么你就调用了它两次。答案是肯定的,你做错了什么——那个循环正在做它应该做的事情。
  • 那是什么?同样,您只是说我做错了什么,没有提供任何建议或可能的解决方案。显然,我来到这里就知道我做错了什么。如果我问的问题不正确,建议替代方案或不回答,这只是在浪费我们的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-10
相关资源
最近更新 更多