Database 此函数是否正确释放资源?

Database 此函数是否正确释放资源?,database,vb.net,visual-studio-2008,resources,Database,Vb.net,Visual Studio 2008,Resources,我正在努力确保我的应用程序中没有留下任何未解决的问题,我关心一些问题,但可能会从中得到答案。我已经“重写”了一些函数,这样我就可以尽量保持所有资源的干净和自由。因此,在本例中,我有一个名为ExecuteReader的函数,它正常返回一个DbDataReader,但我需要传递给它的只是一个SQL字符串,而不是每次都重新创建一个DbCommand。我想确保即使我无法调用dbCommand.Dispose(),它也确实在这样做。非常感谢您的帮助 Public Function ExecuteReade

我正在努力确保我的应用程序中没有留下任何未解决的问题,我关心一些问题,但可能会从中得到答案。我已经“重写”了一些函数,这样我就可以尽量保持所有资源的干净和自由。因此,在本例中,我有一个名为
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数据库,一次只使用一个用户(小应用程序,其增长的可能性非常小),因此我认为没有必要一直关闭和打开连接。也许我错了,不确定。但是,以这种方式使用它,可能可以清理资源?

将DbDataReader传回是个坏主意,因为这要求流保持打开状态,并依赖于调用代码通过处理读取器来完成正确的操作。这也使得关闭底层命令和连接对象变得困难。如果您真的想公开阅读器,可以使用CommandBehavour。当读卡器本身关闭时,这可用于关闭基础连接

dbCommand.ExecuteReader(CommandBehavour.CloseConnection)
由于DbConnection、DbCommand和DbDataReader是一次性的,所以您需要重构代码,以便在代码使用完后能够清理它们。实现这一点的一种方法是在您自己的类中实现IDisposable,并对任何封装的对象进行冒泡处理。然后调用代码可以使用实现,以确保释放资源

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

您应该始终打开和关闭连接,而不是让它保持打开状态。这是一个很好的实践,虽然在一个非常小的应用程序中不太可能,但您可能会遇到问题。您也不应该保留对_dbreaderimo的引用。

传递回DbDataReader是个坏主意,因为这要求流保持打开状态,并依赖调用代码来处理读取器。这也使得关闭底层命令和连接对象变得困难。如果您真的想公开阅读器,可以使用CommandBehavour。当读卡器本身关闭时,这可用于关闭基础连接

dbCommand.ExecuteReader(CommandBehavour.CloseConnection)
由于DbConnection、DbCommand和DbDataReader是一次性的,所以您需要重构代码,以便在代码使用完后能够清理它们。实现这一点的一种方法是在您自己的类中实现IDisposable,并对任何封装的对象进行冒泡处理。然后调用代码可以使用实现,以确保释放资源

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

您应该始终打开和关闭连接,而不是让它保持打开状态。这是一个很好的实践,虽然在一个非常小的应用程序中不太可能,但您可能会遇到问题。您也不应该保留对_dbreaderimo的引用。

从函数返回
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

从函数返回一个
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

检查我的更新代码。我想我应该展示一下我是如何使用它的,看看它是否仍然不安全。谢谢你的回答。是的,在我写了一篇关于不需要打开和关闭它的帖子之后,我想我应该测试一下打开它需要多长时间,而且不需要很长时间,所以我也可以。我感谢您的回答,并将尝试在我使用它的任何地方实现它。请检查我的更新代码。我想我应该展示一下我是如何使用它的,看看它是否仍然不安全。谢谢你的回答。是的,在我写了一篇关于不需要打开和关闭它的帖子之后,我想我应该测试一下打开它需要多长时间,而且不需要很长时间,所以我也可以。谢谢你的帮助