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