如何正确关闭ODP.net连接:dispose()或close()?
这是我的powershell代码:
this is my powershell code :
[void][System.Reflection.Assembly]::LoadFile("C:\DLL\Oracle.ManagedDataAccess.dll")
$OracleConnexion = New-Object Oracle.ManagedDataAccess.Client.OracleConnection('User Id=test;Password="test";Data Source=10.2.2.1/TEST')
$TimeOut = 60
$OracleConnexion.Open()
$Query=$OracleConnexion.CreateCommand()
$Query.CommandText="Select * FROM TEST"
$Query.CommandTimeout = $Timeout
$ExecuteRequete=$Requete.ExecuteReader()
while ($ExecuteRequete.Read()) {
$SiebelLastRecord += $ExecuteRequete.GetDateTime(0).ToString()
}
$OracleConnexion.Close()
因此,我要使用$OracleConnexion.open()
打开ODP.NET连接,然后使用$OracleConnexion.close()
关闭它是否足以正确关闭我与Oracle数据库的连接?还是应该使用$OracleConnexion.Dispose()
?
So I'm opening ODP.NET connection with $OracleConnexion.open()
then closing it with $OracleConnexion.close()
is it sufficient to close properly my connection to Oracle Database? Or should I use $OracleConnexion.Dispose()
?
我每隔5分钟通过Task Scheduler执行一次Powershell ...那么也许我应该使用Dispose()来避免内存饱和吗?
I execute my powershell every 5min via Task scheduler... So maybe Should I use Dispose() to avoid memory saturation?
其他人看起来很像,我最近发现您处于强势状态.在那种情况下,这并不重要.不管shell何时结束,一切都会被清理.我想您可以添加[catch]并在仍然打开的情况下在其中关闭/放置连接,但是我认为只有在您计划让脚本继续运行的情况下才有必要.
It looks like everybody else, I noticed late that you're in powershell. In that case, it doesn't really matter. Everything is going to get cleaned up when the shell ends regardless. I suppose you could add a [catch] and maybe close/dispose the connection there if it's still open, but I think that would only be necessary if you planned on letting your script continue.
我将在下面留下我一直long不休的C#答案.即使它并不真正适用于您的脚本,也可以解释其中的差异(或缺乏差异).
I'll leave my longwinded c# answer below. Even though it doesn't really apply to your script, it explains the difference (or lack thereof).
简短答案(对于c#):
The short answer (for c#):
using (var conn = new OracleConnection(connectionString))
{
}
"using"确保即使在抛出异常的情况下,在块的末尾也调用.Dispose.这样一来,您永远都不会冒着孤立连接的风险,直到垃圾回收最终解决它,并且在数据库连接用完之后还可以.
"using" ensures that .Dispose is called at the end of the block even if an exception is thrown. That way you never risk a connection being orphaned until garbage collection finally gets around to cleaning it up and that might be well after you run out of database connections.
长答案:
使用反射器,您将看到Dispose调用Close:
Using a reflector, you will see that Dispose calls Close:
protected override void Dispose(bool disposing)
{
if (ProviderConfig.m_bTraceLevelPublic)
Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry);
this.m_disposed = true;
this.m_dataSource = string.Empty;
this.m_serverVersion = string.Empty;
try
{
bool flag = this.m_connectionState == ConnectionState.Closed && this.m_oracleConnectionImpl == null;
try
{
if (!disposing)
{
if (!flag)
{
if (OraclePool.m_bPerfNumberOfReclaimedConnections)
OraclePool.PerformanceCounterIncrement(OraclePerfParams.CounterIndex.NumberOfReclaimedConnections, this.m_oracleConnectionImpl, this.m_oracleConnectionImpl.m_cp);
}
}
}
catch (Exception ex)
{
if (ProviderConfig.m_bTraceLevelPublic)
Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Error, ex.ToString());
}
if (!flag)
{
try
{
this.Close();
}
catch (Exception ex)
{
if (ProviderConfig.m_bTraceLevelPublic)
Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Error, ex.ToString());
}
}
try
{
base.Dispose(disposing);
}
catch (Exception ex)
{
if (ProviderConfig.m_bTraceLevelPublic)
Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Error, ex.ToString());
}
try
{
GC.SuppressFinalize((object) this);
}
catch (Exception ex)
{
if (!ProviderConfig.m_bTraceLevelPublic)
return;
Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Error, ex.ToString());
}
}
catch (Exception ex)
{
if (!ProviderConfig.m_bTraceLevelPublic)
return;
Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Error, ex.ToString());
}
finally
{
if (ProviderConfig.m_bTraceLevelPublic)
Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit);
}
}
真的有区别吗?否-非托管资源是使用.Close处理的连接.如果您在finally块中检查了连接状态并调用了.Close(如果它仍处于打开状态),那么您将看不到任何功能上的差异(延迟跟踪除外).
Is there any real difference? No - the unmanaged resource IS the connection which is taken care of with .Close. You'd see no functional difference (other than delayed tracing) if you checked the connection status in a finally block and called .Close there if it was still open.
OracleConnection conn = null;
try
{
conn = new OracleConnection(connectionString);
}
finally
{
if(conn.State != ConnectionState.Closed)
conn.Close();
}
这表示对等对象的推荐模式是使用"using"块.是的,我想您确实可以选择使用close重新打开连接,但我认为这样做不是一件有用的事情.
That said the recommended pattern for idisposible objects is to use a "using" block. Yes I suppose it is true that you have the option to reopen the connection with close, but I don't see that being a useful thing to do.
如果您不使用using或finally,并且不会引发异常并且永远不会调用close/dispose,那么释放与数据库的连接将是不确定的-每当垃圾回收器出现时,都会发生Dispose(false)它-可能会在您耗尽与数据库的连接之后很长时间.
If you didn't use a using or a finally and an exception is thrown and close/dispose is never called, then freeing the connection to the db would be nondeterministic - Dispose(false) would happen whenever the garbage collector got around to it - and that might be long after you run out of connections to your db.
OracleConnection conn = null;
conn = new OracleConnection(connectionString);
conn.Open();
//exception occurs - Close is never called - resource leak!!
conn.Close();