2

這是我的PowerShell代碼:與$OracleConnexion.open()然後用$OracleConnexion.close()關閉它如何正確關閉ODP.net連接:dispose()或close()?

[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數據庫連接?或者我應該使用$OracleConnexion.Dispose()

我每5min通過任務調度程序執行我的powershell ...所以也許我應該使用Dispose()來避免內存飽和?

+0

最好的做法是調用Dispose(),特別是如果使用ODP.NET非託管。原因在於垃圾收集器清理速度可能很慢,並且可能導致問題,例如連接/光標過多打開太久。 –

回答

4

它看起來像其他人,我注意到你很晚才知道你在使用PowerShell。在這種情況下,這並不重要。無論何時shell都會結束,所有內容都將被清理乾淨。我想你可以添加一個[catch],也許關閉/處理連接,如果它仍然是開放的,但我認爲只有當你計劃讓腳本繼續時纔有必要。

我會在下面留下我的longwinded c#答案。儘管它並不適用於您的腳本,但它解釋了其差異(或缺乏)。

簡短的回答(對於C#):

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

「使用」確保.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); 
    } 
} 

有什麼真正的區別?否 - 非託管資源是需要處理的連接。關閉。如果您在finally塊中檢查了連接狀態,並且調用了.Close,如果它仍然處於打開狀態,您將看不到任何功能差異(延遲跟蹤除外)。

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

也就是說,推薦的不可分配對象模式是使用「使用」塊。是的,我認爲你可以選擇重新打開連接,但我認爲這不是一件有用的事情。

如果你沒有使用一個或最後和拋出一個異常,並關閉/處置不會被調用,然後釋放到數據庫的連接將是不確定的使用 - 當垃圾收集處置了(假)會發生圍繞它 - 這可能會很長時間後,你連接到你的數據庫。

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

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

    conn.Close(); 
5

關閉關閉連接並允許您重新打開它。

配置關閉連接,如果它還沒有關閉,也處置它,所以你不能重新打開它。

如果該資源處於打開狀態,則使用配置 - 配置釋放資源的內存,然後運行良好的.dispose方法將關閉該資源。

的Dispose()與關閉()與ConnectionPooling: https://community.oracle.com/thread/165664?start=0&tstart=0

+0

所以我應該關閉然後配置連接?好點嗎?它在服務器端嗎? –

+0

您提供的鏈接是Sql服務器連接。我相信oracle不是以同樣的方式實現的...... – billybob

+0

我把這個解釋爲close和dispose之間的區別,但是你是對的,當我們使用Oracle時,我們需要參考Oracle編輯的。 – TheCodeLord

1

我想包通過using語句的連接。完成連接後,請在添加括號之前將其關閉。是100%的安全,我會做這樣的事情:

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

編輯:

我加了Con.Close(),因爲在過去的dispose不正確的ODP.NET實現。連接保持開放。我們必須強制手動關閉連接,這就是爲什麼在這個例子中,我指定了Close。資源它們實現IDisposable

+0

Dispose怎麼樣? – JoshYates1980

+1

處置意味着什麼? 'OracleConnection'繼承自實現'IDisposable'接口的'DbConnection'。配置將自動調用。 – billybob

1

更標準的實施是由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()

A sample在使用Oracle.DataAccess的oracle文檔中也鼓勵使用Dispose