Problems with CDaoDatabase and multiple threads


I am writing a program that handles database operations for a IVR telephone system. I have numerous threads running that handle the db operations. The problem is that when many calls hangup at the same time my program has to log information to an Access database the threads crash on the open database call. I use a global critical section object around the code and I open the database in exclusive non-shared mode but still there are crashes. Note, that this works for a few hours under heavy stress but eventually crashes.

My question is that, has anyone encountered such problems with MFC Dao classes. Also, does AfxDaoInit and AfxDaoTerm have to always be called before and after any database operations? These functions seem to create their own threads and I have a feeling that they are screwing up. The crash seems to happen inside the Dao350.dll because when I click on the "Cancel" button on the famous Access Violation window MSStudio opens up with Dao350.dll dissambeley.

Please, let me know if this question is understandable. Any help would be appreciated. Thanks.
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

vachoohoConnect With a Mentor Commented:
CDatabase * oDb = new CDatabase;
CRecordset rs = new CRecordset(oDb);

// run some querries

delete rs;
delete oDb

Database will not be closed if you have recordsets on it.
THus close and delete recordset first then close and delete database object.

Hope this works

MSDN say, that AfxDaoInit you should call before working with database...

and AfxDaoTerm you program should call automatically, but I see, tham my program not call it, and I call it manually...
Database always has one or other problems when used in threads
Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Call AfxDaoInit() in EACH thread you created and AfxDaoTerm() only once in your application clean-up code.

Also you need to call AfxDaoInit() if you use callback functions.

Hope this helps
sinisterAuthor Commented:
Currently I am opening, running query, and then closing the database, do I have to call AfxDaoInit before I do the database open?
If you do it in your main application thread then NO

If you do it in separate thread or callback functions you need to call AfxDaoInit() BEFORE any call to DAO functions in the current thread.

If you want to access the Jet database from a multithreaded app, then I'll suggest that you switch to OLEDB instead.

OLEDB has full support for multithreaded access to the database.

Take a look at the classes CDataSource, CSession, CRowset.

Here is an example of opening a jet database using OLEDB:

HRESULT TestFunction()
    CDataSource ds;
    CSession session;

    wchar_t* pwcPath = "C:\\MyData.mdb";

    CDBPropSet dbinit(DBPROPSET_DBINIT);
    dbinit.AddProperty(DBPROP_INIT_DATASOURCE, pwcPath);
    dbinit.AddProperty(DBPROP_INIT_MODE, (long)(DB_MODE_READWRITE));
    dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)DBPROMPT_NOPROMPT);
    dbinit.AddProperty(DBPROP_INIT_LCID, (long)GetSystemDefaultLCID());
    dbinit.AddProperty(DBPROP_AUTH_USERID, OLESTR("Admin"));
    dbinit.AddProperty(DBPROP_AUTH_PASSWORD, OLESTR(""));
    hr = ds.Open(CLSID_JETOLEDB_4_00, &dbinit);
    hr = ds.Open(CLSID_JETOLEDB_3_51, &dbinit);
        return hr;
    hr = session.Open(ds);
        return hr;

    // ... Do something with it ...
    // ....


    return S_OK;
sinisterAuthor Commented:
Can someone tell me if MFC's CDatabase class is thread safe, it would be much easier for me change my code to CDatabase from CDaoDatabase rather than OLE DB or ADO.
Yes MFC's CDatabase and CRecordset is thread-safe classes. YOu can use them in separate threads without any kind of additional preparations for that.
sinisterAuthor Commented:

Can someone tell me how I can get rid of the CDatabase object when I am done with it. Here is an abbreviation of the code:

CDatabase * oDb = new CDatabase;
CRecordset rs(oDb);

// run some querries

delete oDb;

However, when my function returns I get an exception because the pointer that CDatabase uses is still valid. This exception happens inside CObject.


By the way, who wants the points
sinisterAuthor Commented:
Great thanks for everything. I decided to use a global database object for all threads and then protect any query executions with critical secitons. I had to minimize the amount of opens and closes because memory was jumping up like crazy. I am still having crashes if implement transaction processing. Are there any problems with using ODBC to get at MS ACCESS rather than DAO. I am using CDatabase so I can have many threads query the db asynchronously
All Courses

From novice to tech pro — start learning today.