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\'
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).
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.
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.