3

これは私の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()

それで、ODP.NET接続を開いてから閉じていますが、Oracle Databaseへの接続を適切に閉じるには十分ですか$OracleConnexion.open()? $OracleConnexion.close()または、使用する必要があります$OracleConnexion.Dispose()か?

タスク スケジューラを介して 5 分ごとに PowerShell を実行しています...メモリの飽和を避けるために Dispose() を使用する必要がありますか?

4

4 に答える 4

6

他のみんなと同じように見えますが、あなたが powershell にいることに遅く気づきました。その場合は特に問題ありません。 シェルが終了すると、すべてがクリーンアップされます。[catch] を追加して、まだ開いている場合は接続を閉じたり破棄したりできると思いますが、スクリプトを続行する予定がある場合にのみ必要だと思います。

長々とした c# の回答を以下に残しておきます。スクリプトには実際には当てはまりませんが、違い (または違い) を説明しています。

短い答え (c# の場合):

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

「使用」により、例外がスローされた場合でも、ブロックの最後で .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 ブロックで接続ステータスを確認し、まだ開いている場合はそこで .Close を呼び出した場合、(遅延トレース以外の) 機能的な違いは見られません。

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

そうは言っても、識別可能なオブジェクトの推奨されるパターンは、「使用中」ブロックを使用することです。はい、クローズで接続を再開するオプションがあるのは事実だと思いますが、それが有用なことだとは思いません。

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();
于 2016-03-01T14:56:06.233 に答える
5

Close は接続を閉じ、再び開くことができるようにします。

Dispose は、接続が閉じられていない場合は接続を閉じます。また、再度開くことができないように破棄します。

dispose を使用 - dispose はリソースのメモリを解放します。そのリソースが開いている場合は、適切に動作する .dispose メソッドがリソースを閉じます。

Dispose() vs. ConnectionPooling を使用した Close(): https://community.oracle.com/thread/165664?start=0&tstart=0

于 2016-02-29T15:45:28.693 に答える
2

実装するリソースのより標準的な実装IDisposableは、次のようにラップすることusingです。

using (OracleConnection connection = new OracleConnection(connectionString)){
    using (OracleCommand command = new OracleCommand(sql, connection))
        using (OracleDataReader reader = cmd.ExecuteReader())
        {
        }
    connection.Close(); //optional
}

.Dispose実行ブロックの後に実装するのと同じです。内部的にDisposeは、クロージングも処理します。.Close()ただし、コマンド ブロックの後に を呼び出すこともできます。

を使用するオラクルのドキュメントのサンプルOracle.DataAccessでは、​​あまりにも使用することをお勧めしDisposeます。

于 2016-02-29T15:57:46.350 に答える
1

using ステートメントで接続をラップします。接続が完了したら、ブラケットを追加する前に接続を閉じます。100% 安全にするには、次のようにします。

using(OracleConnexion Con = new OracleConnection (...))
{
    Con.Open()
    ...
    Con.Close()
}

編集:

以前は ODP.NET で が正しく実装されていなかっCon.Close()たため、を追加しました。dispose接続は開いたままでした。手動で接続を強制的に閉じる必要があったため、この例ではClose.

于 2016-02-29T15:54:51.937 に答える