此功能是否正确释放资源?

时间:2010-09-23 13:14:59

标签: database vb.net visual-studio-2008 resources

我正在努力确保我不会在我的应用程序中留下任何松散的结尾,并且我会关注一些,但可能会得到我的回答。我已经“覆盖”了一些功能,这样我就可以尝试将所有资源尽可能地保持干​​净和自由。所以在这个例子中,我有一个名为ExecuteReader的函数,它正常返回DbDataReader,但我必须传递给它的是一个SQL字符串,而不是每次都重新创建一个DbCommand。我想确保即使我无法呼叫dbCommand.Dispose()它实际上是这样做的。任何和所有的帮助表示赞赏。

Public Function ExecuteReader(ByVal strSQL As String) As DbDataReader
    Dim dbCommand = _dbConnection.CreateCommand()
    dbCommand.CommandText = strSQL
    dbCommand.Prepare()
    Return dbCommand.ExecuteReader()
End Function

我正在考虑使用using语句,但我记得看到一个帖子,有人说他们认为这导致他们在using语句中返回时出现问题。此外,我不确定这是否应该是社区维基。如果应该,请告诉我。感谢。

代码更新

以下是我如何使用它的示例。

Public Sub RevertDatabase()
    'This function can be used whenever all changes need to be undone, but was created'
    'for saving the data as a .out file.  It sets all changes back to their original value.'

    'Set the data reader to all parts and columns that were changed.'
    _dbReader = ExecuteReader("SELECT PART_ID, PART_PREV_VALUE, REPORT_COLUMN_NAME FROM REPORTS WHERE PART_PREV_VALUE NOT NULL")
    'Create an instance of the Command class.'
    Dim cmd = New Command()

    While _dbReader.Read()
        'For each part and columns that has been changed, set the values in the'
        'new cmd variable and then update the value using the same function'
        'that is used whenever a value is changed in the data grid view.'
        cmd.CommandString = _dbReader("REPORT_COLUMN_NAME").ToString().Replace("_", " ")
        cmd.Value = _dbReader("PART_PREV_VALUE").ToString()
        cmd.ID = _dbReader("PART_ID").ToString()
        UpdateValue(cmd)
    End While

    'Close the reader.'
    _dbReader.Close()
End Sub

在这里,我将_dbReader设置为我从函数中获取的内容,最后关闭_dbReader。我没有关闭连接,因为每次进行查询时都不会打开它。这是一个SQLite数据库,一次只能有一个用户使用(小应用程序的可能性非常小,它会增长)所以我认为没有必要一直关闭和打开连接。也许我错了,不确定。以这种方式使用它,可以清理资源吗?

2 个答案:

答案 0 :(得分:3)

传回DbDataReader是一个坏主意,因为这要求流保持打开并依赖于调用代码来通过处理读取器来做正确的事情。这也使得关闭底层命令和连接对象变得困难。如果您真的想要公开读者,一种方法是使用CommandBehavour。当阅读器本身关闭时,这可用于关闭底层连接。

dbCommand.ExecuteReader(CommandBehavour.CloseConnection)

由于DbConnection,DbCommand和DbDataReader是Disposable,您需要重构代码以允许在代码完成后清除这些代码。一种方法是实现这一点,即在您自己的类中实现IDisposable,并将bubble配置为任何封装对象。然后,调用代码可以实现使用以确保释放资源。

Using helper As New DatabaseHelper()
   Using reader As IDataReader = helper.LoadSomeDataReader()

      ' do something with reader

   End Using
End Using

<强>更新

你的第二段代码会变得更像:

Public Sub RevertDatabase()
   Using _dbReader As IDataReader = ExecuteReader(...)

      While _dbReader.Read()

         Using cmd As New Command()
            cmd.CommandString = _dbReader("REPORT_COLUMN_NAME").ToString().Replace("_", " ")
            cmd.Value = _dbReader("PART_PREV_VALUE").ToString()
            cmd.ID = _dbReader("PART_ID").ToString()
            UpdateValue(cmd)
         End Using

       End While

    End Using
 End Sub

您应始终打开和关闭连接,而不是将其保持打开状态。它可以实践,虽然在非常小的应用程序中极不可能,但您可能会遇到问题。您也不应该保留对_dbReader IMO的引用。

答案 1 :(得分:0)

从函数中返回IDisposable实例非常好。实例的所有权正从函数传递给调用者,现在调用者有责任调用Dispose。调用IDbCommand.ExecuteReader时,这与游戏完全相同。

您绝对应该使用Using语句。它使代码更具可读性,因为它会自动插入调用Dispose方法的正确try-finally块。我不知道你所指的问题的细节,但你不应该自己有任何问题,因为你没有做任何与众不同的事情。

Public Sub RevertDatabase() 
    Using dbReader As DbDataReader = ExecuteReader(...) 
      // Use the data reader here.
    End Using
End Sub