如何正确关闭ODP.net连接:dispose()或close()? [英] How to properly close ODP.net connection : dispose() or close()?

查看:131
本文介绍了如何正确关闭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();

这篇关于如何正确关闭ODP.net连接:dispose()或close()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆