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?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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
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
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

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


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.