2016-04-04 140 views
1

我創建了一個應用程序,它調用SQLDriverConnect連接到名爲'MyDB'的MS SQL Server數據庫。做了一些事情之後,它調用SQLDisconnect.But然後SSMS無法刪除'MyDB'。這意味着一些資源沒有正確關閉。只有在退出該過程之後,SSMS纔會刪除它(,即操作系統釋放它們的),並且所有SQLHENV和SQLHDBC都已正確釋放。下面 代碼:如何正確釋放ODBC對象?

SMARTHSTMT::~SMARTHSTMT() 
{ 
    if (!m_hstmt) return; 
    SQLFreeStmt(m_hstmt, SQL_CLOSE); 
    SQLFreeStmt(m_hstmt, SQL_UNBIND); 
    SQLFreeStmt(m_hstmt, SQL_RESET_PARAMS); 
    SQLFreeHandle(SQL_HANDLE_STMT, m_hstmt); 
    m_hstmt = nullptr; 
}; 

我怎樣才能找到哪個對象不會被釋放?我應該採取其他考慮嗎?任何想法或幫助表示讚賞。 編輯:用於斷開代碼:

void AConnection::uDisconnect() 
{ 
    if (m_hdbc) 
    { 
     SQLDisconnect(m_hdbc); 
     SQLFreeHandle(SQL_HANDLE_DBC, m_hdbc); 
     m_hdbc = nullptr; 
    } 
    if (m_henv) 
    { 
     SQLFreeHandle(SQL_HANDLE_ENV, m_henv); 
     m_henv = nullptr; 
    } 
} 
+0

什麼是調用SQLDisconnect的結果呢?你發佈的代碼只是爲了釋放語句句柄,連接和環境處理如何? – erg

+0

使用SQLFreeHandle釋放它們。我只發佈銷燬語句的代碼,因爲聲明被廣泛使用,他們很可能忘記釋放它們。 –

+0

如果釋放連接句柄,如果有任何打開的語句句柄來自該連接句柄,則應該得到一個SQLERROR作爲返回值,而不是? – erg

回答

0

您可以檢查是否SQLDisconnect()回報SQL_ERROR。如果是這樣的話,一個聲明可能仍然是開放的,或者一個交易(如你檢測到的)仍然是開放的。

交易在ODBC處理是(簡化)這樣的:

默認情況下,提交自動啓用。一切都開始一個新的事務,如果語句成功,事務就被提交。如果你還沒有改變提交模式,它會讓我困惑,交易仍然是開放的。

如果您已禁用自動提交,則必須手動調用SQLEndTrans(...)來提交或回滾任何正在進行的事務。據我所知,如果有任何事務仍然處於打開狀態,ODBC就無法查詢驅動程序。

當你提到SQLEndTrans()的調用時,我想你已經禁用了自動提交。看看我的消息來源,我發現我總是在關閉連接句柄之前做一個回滾 - 也許是因爲同樣的問題,我不記得確切(它的舊代碼)。

無論如何,如果您啓用了手動提交模式,我只是建議您在關閉連接句柄之前進行回滾。也許有將是對SQL服務器端工具來分析一下什麼是當時恰好開放更多的細節..

在這裏看到更多的細節:https://msdn.microsoft.com/en-us/library/ms131281.aspx

+0

謝謝。你的回答非常明確和有用。正如你所猜測的,我禁用自動提交併調用SQLEndTrans來提交或回滾。我也決定回滾SQLDisconnect。這是我最後一個問題:爲什麼諸如SQLColumns,SQLTables,SQLStatistics之類的語句啓動一個事務? –

+0

@MohamadrezaAbdolahzadeh:我不知道爲什麼catalog-functions開始一個事務。我想我一直在努力解決同樣的問題,並沒有找到任何有用的解決方案。也許這是值得作爲獨立問題添加的。 – erg