c# - 如何正确关闭 ODP.net 连接 : dispose() or close()?

标签 c# powershell powershell-3.0 odp.net oracle-manageddataaccess

这是我的 powershell 代码:

[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() 吗?

我通过任务调度程序每 5 分钟执行一次 powershell...所以也许我应该使用 Dispose() 来避免内存饱和?

最佳答案

看起来和其他人一样,我最近才注意到您使用的是 powershell。在那种情况下,这并不重要。无论如何,当 shell 结束时,一切都会被清理干净。我想您可以添加一个 [catch],如果它仍然打开,也许可以关闭/处理那里的连接,但我认为只有在您计划让您的脚本继续时才有必要这样做。

我将在下面留下冗长的 C# 答案。尽管它并不真正适用于您的脚本,但它解释了差异(或缺乏差异)。

简短的回答(对于 c#):

using (var conn = new OracleConnection(connectionString))
{
}

“using”确保在 block 末尾调用 .Dispose,即使抛出异常也是如此。这样一来,您永远不会冒连接被孤立的风险,直到垃圾收集最终开始清理它,这可能在您用完数据库连接之后很好。

长答案:

使用反射器,您会看到 Dispose 调用了 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 block 中检查连接状态并调用 .Close(如果它仍处于打开状态),您将看不到任何功能差异(除了延迟跟踪)。

  OracleConnection conn = null;
  try
  {
    conn = new OracleConnection(connectionString);
  }
  finally
  {
    if(conn.State != ConnectionState.Closed)
      conn.Close();
  }

那是说,对于一次性对象,推荐的模式是使用“using” block 。是的,我想您确实可以选择通过关闭重新打开连接,但我认为这不是一件有用的事情。

如果您没有使用 using 或 finally 并且抛出异常并且永远不会调用 close/dispose,那么释放与数据库的连接将是不确定的 - Dispose(false) 会在垃圾收集器四处走动时发生到它 - 这可能会在您用完与数据库的连接后很久。

    OracleConnection conn = null;
    conn = new OracleConnection(connectionString);
    conn.Open();

    //exception occurs - Close is never called - resource leak!!

    conn.Close();

关于c# - 如何正确关闭 ODP.net 连接 : dispose() or close()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35703559/

相关文章:

c# - JQuery 数据表将列类添加到动态内容

c# - 如何将Azure Function日志发送到blob存储?

c# - 根据点对划分一个矩形

powershell - 如何在Powershell中加载WPFToolkit程序集

powershell - 解析Powershell变量

c# - DataGrid - 新数据到达时重置网格选择

powershell - 移动项目 : Illegal characters in path - filename with spaces

powershell - 在 Powershell 中设置像 yyyy-mm-dd 这样的默认日期格式?

powershell - 从当前日期循环到负15天

powershell - 在powershell中迭代多维哈希表