CRecordset::snapshot doesn't work in VS2012 anymore - what's the alternative?

后端 未结 3 579
终归单人心
终归单人心 2021-01-14 09:04

Apparently, in VS2012, SQL_CUR_USE_ODBC is deprecated. [Update: it appears that the cursors library has been removed from VS2012 entirely].

MFC\'s CDatabase doesn\'

相关标签:
3条回答
  • 2021-01-14 09:31

    If anyone else runs into this issue, here's what seems to be the answer:

    For ODBC to an Access database, connect using CDatabase mydb; mydb.OpenEx(.., 0), so that you ask the system not to load the cursor library.

    Then for the recordsets, use dynaset CMyRecordset myrs; myrs.Open(CRecordset::dynaset, ...).

    Finally, you must make sure that your tables have a primary key in order to use dynasets (keysets).

    0 讨论(0)
  • 2021-01-14 09:38

    Derive CDatabase and override OpenEx. In your derived class CMyDatabase, replace the call to AllocConnect to MyAllocConnect. Obviously, your MyAllocConnect function should call SQLSetConnectOption with the desired parameter:

    // Turn on cursor lib support
    if (dwOptions & useCursorLib)
    {
        AFX_SQL_SYNC(::SQLSetConnectOption(m_hdbc, SQL_ODBC_CURSORS, SQL_CUR_USE_ODBC));
        // With cursor library added records immediately in result set
        m_bIncRecordCountOnAdd = TRUE;
    }
    

    Then use your CMyDatabase class instead of CDatabase for all your queries.

    0 讨论(0)
  • 2021-01-14 09:52

    I found a solution that appears to work. I overrode OpenEx the exact same way VS 2012 has it because we need that to call the child version of AllocConnect since it is not virtual in the parent. I also overrode AllocConnect as mentioned. In the derived version of CDatabase, try the following code:

    MyCDatabase.h

    BOOL OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions = 0);
    void AllocConnect(DWORD dwOptions);
    

    MyCDatabase.cpp

    BOOL MyCDatabase::OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions)
    {
    ENSURE_VALID(this);
    ENSURE_ARG(lpszConnectString == NULL || AfxIsValidString(lpszConnectString));
    ENSURE_ARG(!(dwOptions & noOdbcDialog && dwOptions & forceOdbcDialog));
    
    // Exclusive access not supported.
    ASSERT(!(dwOptions & openExclusive));
    
    m_bUpdatable = !(dwOptions & openReadOnly);
    
    TRY
    {
        m_strConnect = lpszConnectString;
    
        DATA_BLOB connectBlob;
        connectBlob.pbData = (BYTE *)(LPCTSTR)m_strConnect;
        connectBlob.cbData = (DWORD)(AtlStrLen(m_strConnect) + 1) * sizeof(TCHAR);
        if (CryptProtectData(&connectBlob, NULL, NULL, NULL, NULL, 0, &m_blobConnect))
        {
            SecureZeroMemory((BYTE *)(LPCTSTR)m_strConnect, m_strConnect.GetLength() * sizeof(TCHAR));
            m_strConnect.Empty();
        }
    
        // Allocate the HDBC and make connection
        AllocConnect(dwOptions);
        if(!CDatabase::Connect(dwOptions))
            return FALSE;
    
        // Verify support for required functionality and cache info
        VerifyConnect();
        GetConnectInfo();
    }
    CATCH_ALL(e)
    {
        Free();
        THROW_LAST();
    }
    END_CATCH_ALL
    
    return TRUE;
    }
    
    void MyCDatabase::AllocConnect(DWORD dwOptions)
    {
    CDatabase::AllocConnect(dwOptions);
    
    dwOptions = dwOptions | CDatabase::useCursorLib;
    
    // Turn on cursor lib support
    if (dwOptions & useCursorLib)
    {
        ::SQLSetConnectAttr(m_hdbc, SQL_ATTR_ODBC_CURSORS, (SQLPOINTER)SQL_CUR_USE_ODBC, 0);
        // With cursor library added records immediately in result set
        m_bIncRecordCountOnAdd = TRUE;
    }
    }
    

    Please note that you do not want to pass in useCursorLab to OpenEx at first, you need to override it in the hacked version of AllocConnect.

    Also note that this is just a hack but it appears to work. Please test all your code to be sure it works as expected but so far it works OK for me.

    0 讨论(0)
提交回复
热议问题