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't use it anymore (whereas it was the default for VS2010 and earlier versions of MFC), but instead uses SQL_CUR_USE_DRIVER.
Unfortunately, SQL_CUR_USE_DRIVER doesn't work properly with the Jet ODBC driver (we're interacting with an Access database). The driver initially claims to support positional operations (but not positional updates), but when an attempt is made to actually query the database, all concurrency models fail until the MFC library drops down to read-only interaction with the database (which is not going to fly for us).
Questions
- Is this MS's latest attempt to force devs to move away from Jet based datasources and migrate to SQL Express (or the like)?
- Is there another modality that we should be using to interact with our Access databases through VS 2012 versions of MFC/ODBC?(1)
See also: http://social.msdn.microsoft.com/Forums/kk/vcmfcatl/thread/acd84294-c2b5-4016-b4d9-8953f337f30c
Update: Looking at the various options, it seems that the cursor library has been removed from VS2012's ODBC library. Combined with the fact that Jet doesn't correctly support positional updates(2), it makes "snapshot" mode unusable. It does appear to support "dynaset" as long as the underlying tables have a primary key. Unkeyed tables are incompatible with "dynaset" mode(3). So - I can stick with VS 2010, or I can change my tables to include an autonumber or something similar in order to ensure a pkey is available so I can use dynaset mode for the recordsets.
(1) e.g. should we be using a different open type for CRecordset? We currently use CRecordset::snapshot. But I've never really understood the various modes snapshot, dynamic, dynaset. A quick set of "try each" has failed to get a working updatable interface to our access database...
(2) it claims to when queried initially, but then returns errors for all concurrency modes that it previously claimed to support
(3) "dynamic" is also out, since Jet doesn't support it at all (from what I can tell from my tests).
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).
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
MyCDatabase.cpp
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.
Derive CDatabase and override OpenEx. In your derived class
CMyDatabase
, replace the call toAllocConnect
toMyAllocConnect
. Obviously, yourMyAllocConnect
function should call SQLSetConnectOption with the desired parameter:Then use your
CMyDatabase
class instead ofCDatabase
for all your queries.