DataReader比连接对象更长

时间:2012-11-16 17:40:58

标签: vb.net

请查看以下代码:

Private objCommand As SQLCommand 

Public Overrides Function ExecuteDataReader(ByVal strCommandType As String, ByVal sqlCommandString As String) As DbDataReader
    Dim objDR As SqlDataReader

    Try
        _objCon = getConnection()
        _objCon.Open()
        Using _objCon
            Using _objCommand
                _objCommand.Connection = _objCon
                _objCommand.CommandText = sqlCommandString
                _objCommand.CommandType = strCommandType
                objDR = _objCommand.ExecuteReader
                ExecuteDataReader = objDR
            End Using
        End Using
    Catch ex As Exception
        Throw
    Finally
        _objCon = Nothing
        _objCommand.Dispose()
        _objCommand = Nothing
        objDR = Nothing
    End Try
End Function

DataReader将关闭,因为它在关闭连接对象时关闭。 DataReader如何比连接对象更长久?

我找了类似的问题,我找到了这个问题:DataReader not closed when Connection is closed, consequences?。但是,它没有回答我的具体问题。

2 个答案:

答案 0 :(得分:2)

您的连接过早关闭的原因是您在退出Using块之前不会从函数返回。离开使用块的行为将强制您的连接立即关闭。将datareader设置为返回的对象是不够的。即使使用显式的Return语句也是不够的......离开函数仍然意味着离开Using块,所以在你开始使用datareader之前你的连接仍然关闭。


为了解决这些问题,我使用了这样的模式:

Public Iterator Function ExecuteDataReader(Of T)(ByVal sql As String, ByVal addParams as Action(Of SqlParameterCollection), ByVal castRow As Funnction(Of IDataRecord, T)) As IEnumerable(Of T)

    Using cn As SqlConnection = getConnection(), _
          cmd As New SqlCommand(sql, cn)

        addParams(cmd.Parameters)
        cn.Open()

        Using rdr As SqlDataReader = cmd.ExecuteReader()
            While rdr.Read()
                Yield castRow(rdr)
            End While
        End Using
    End Using
End Function

然后我会调用这个函数:

Dim results As IEnumerable(Of Customer) = ExecuteDataReader( _
           "SELECT * FROM Customer WHERE Sales> @MinSales", _
      Sub(p) p.Add("@MinSales", SqlDbType.Double).Value = 10000.0, _
      Function(r) New Customer() With {Name=r("Name"), Address=r("Address"), Sales=r("Sales") })

For Each c As Customer in results
   '...
Next

让我们稍微讨论一下这种模式,因为有些事情可能会让人感到困惑......即我想要覆盖委托的论点。

首先是addParameter参数。您需要了解的是您的原始模式被严重破坏,因为它会强制您创建充满Sql注入漏洞的代码,因为没有其他方法可以发送参数信息。这是一个巨大的问题。谢天谢地,它很容易解决。这就是addParameter参数的用途。这不是唯一的方法 - 也就是说,你可以做一些简单的事情,如传递一个键/值/类型的数组 - 但我喜欢它,因为它避免了重复工作通过数组或复制内存存储参数数据两次。

接下来是castRow参数。这是必要的,因为没有它你会遇到与你的例子有关的类似问题。在这里,代码仍然可以运行,但是因为你在其他地方继续产生相同的目标代码,最终所有人都会使用结果中的最终记录。通过这种方式,您可以获得正确的预期结果,并以强类型方式获得它们。

接下来,希望你已经熟悉Iterator和Yield关键字了,但是因为它们对VB.Net来说比较新,所以如果你不是。只要知道它们会导致编译器将此代码转换为可以迭代datareader对象的内容。

答案 1 :(得分:0)

你可以使用ExecuteReader的重载并传递CommandBehaviour.Close,然后当读者被处理掉其余部分时,它会变得混乱,你就会失去对生命周期的控制。

我的推荐是不要这样做,我在一个项目中做了,虽然我仍然喜欢DataReader作为轻量级访问,并且不喜欢Datatable,我不再传递raeders,错误的范围太大。这是代码,连接池和Garbarge收集器之间的持续争斗,你将赢得胜利。

使用DataTable,EF,Linq或只是一个老式的IEnumberable

相关问题