Sql server 如何正确释放ODBC对象?

Sql server 如何正确释放ODBC对象?,sql-server,odbc,Sql Server,Odbc,我创建了一个应用程序,它调用SQLDriverConnect连接到一个名为“MyDB”的MS SQL Server数据库。完成一些操作后,它调用SQLDisconnect。但是SSMS无法删除“MyDB”。这意味着某些资源未正确关闭。只有在退出流程后,SSMS才会删除它(即操作系统将其释放),并且所有SQLHENV和SQLHDBC都会正确释放。 代码如下: SMARTHSTMT::~SMARTHSTMT() { if (!m_hstmt) return; SQLFreeStmt(

我创建了一个应用程序,它调用
SQLDriverConnect
连接到一个名为“MyDB”的MS SQL Server数据库。完成一些操作后,它调用SQLDisconnect。但是SSMS无法删除“MyDB”。这意味着某些资源未正确关闭。只有在退出流程后,SSMS才会删除它(即操作系统将其释放),并且所有SQLHENV和SQLHDBC都会正确释放。 代码如下:

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;
    }
}

您可以检查
SQLDisconnect()
是否返回
SQL\u错误
。如果是这种情况,则语句可能仍处于打开状态,或者事务(如您检测到的)仍处于打开状态

ODBC中的事务处理(简化)如下:

默认情况下,启用自动提交。所有内容都启动一个新事务,如果语句成功,则提交事务。如果您没有更改提交模式,那么事务仍然处于打开状态,这让我感到困惑

如果禁用了自动提交,则必须手动调用
SQLEndTrans(…)
以提交或回滚任何正在进行的事务。据我所知,在ODBC中,如果有任何事务仍处于打开状态,则无法查询驱动程序

当您提到对
SQLEndTrans()
的调用时,我想您已经禁用了自动提交。查看我的源代码,我发现我总是在关闭连接句柄之前进行回滚-可能是因为同样的问题,我记不清了(它的旧代码)

无论如何,如果您启用了手动提交模式,我建议您在关闭连接句柄之前进行回滚。也许在SQL Server端会有一些工具来分析更多关于当时什么是完全开放的细节


有关更多详细信息,请参见此处:

您可以检查
SQLDisconnect()
是否返回
SQL\u错误。如果是这种情况,则语句可能仍处于打开状态,或者事务(如您检测到的)仍处于打开状态

ODBC中的事务处理(简化)如下:

默认情况下,启用自动提交。所有内容都启动一个新事务,如果语句成功,则提交事务。如果您没有更改提交模式,那么事务仍然处于打开状态,这让我感到困惑

如果禁用了自动提交,则必须手动调用
SQLEndTrans(…)
以提交或回滚任何正在进行的事务。据我所知,在ODBC中,如果有任何事务仍处于打开状态,则无法查询驱动程序

当您提到对
SQLEndTrans()
的调用时,我想您已经禁用了自动提交。查看我的源代码,我发现我总是在关闭连接句柄之前进行回滚-可能是因为同样的问题,我记不清了(它的旧代码)

无论如何,如果您启用了手动提交模式,我建议您在关闭连接句柄之前进行回滚。也许在SQL Server端会有一些工具来分析更多关于当时什么是完全开放的细节


有关更多详细信息,请参见此处:

SQLDisconnect的结果是什么?您发布的代码只是关于释放语句句柄,那么连接和环境句柄呢?它们是使用SQLFreeHandle释放的。我只发布了销毁语句的代码,因为语句被广泛使用,它们很可能会忘记释放它们。如果释放连接句柄,如果有来自该连接句柄的任何打开的语句句柄,则应将SQLERROR作为返回值,不是吗?是的,我忘了检查SQLDisconnect的结果。它返回SQL\u错误,存在活动事务。这个sql命令序列导致一个打开的事务,原因我不知道。创建表,创建索引,SQLEndTrans,插入,创建表,创建索引,SQLEndTrans,SQLColumns。此时SQLDisconnect返回SQLU错误,我不知道SQLColumns为什么开始事务。请你把这个作为一个答案,这样我就接受了,问题就结束了。SQLDisconnect的结果是什么?您发布的代码只是关于释放语句句柄,那么连接和环境句柄呢?它们是使用SQLFreeHandle释放的。我只发布了销毁语句的代码,因为语句被广泛使用,它们很可能会忘记释放它们。如果释放连接句柄,如果有来自该连接句柄的任何打开的语句句柄,则应将SQLERROR作为返回值,不是吗?是的,我忘了检查SQLDisconnect的结果。它返回SQL\u错误,存在活动事务。这个sql命令序列导致一个打开的事务,原因我不知道。创建表,创建索引,SQLEndTrans,插入,创建表,创建索引,SQLEndTrans,SQLColumns。此时SQLDisconnect返回SQLU错误,我不知道SQLColumns为什么开始事务。请你把这个作为答案,这样我就接受了,问题就结束了。谢谢。你的回答很清楚,也很有用。正如您所猜测的,我禁用了自动提交并调用SQLEndTrans进行提交或回滚。我也决定在SQLDisconnect之前回滚。这是我的最后一个问题:为什么SQLColumns、SQLTables、SQLStatistics等语句会启动事务?@MohamadrezaAbdolahzadeh:我不知道目录函数为什么会启动事务。我想我也遇到过同样的问题,没有找到任何有用的解决办法。也许这是一个值得补充的独立问题。谢谢。你的回答很清楚,也很有用。正如您所猜测的,我禁用了自动提交并调用SQLEndTrans进行提交或回滚。我也决定在SQLDisconnect之前回滚。这是我的最后一个问题:为什么SQLColumns、SQLTables、SQLStatistics等语句会启动事务?@MohamadrezaAbdolahzadeh:我不知道目录函数为什么会启动tr