Microsoft’s Visual C++ on-line help says that DAO is safe to use in DLL’s.
Therefore, I created a DLL which I use to access the same database my main application thread
is accessing, in order to do a background report with one worker thread..
From the main application’s point of view it is creating wrapper objects in a DLL. The wrapper objects,
in turn, access the database and return the results to the application.
It is a single-threaded DLL but it could probably be modified to be thread-safe by using locks.
I list the code for one wrapper class here but you could put many different recordset wrappers into the DLL project.
Here’s some of the code in my DLL:
class CMyRecordsetWrapper : public CCmdTarget { DECLARE_DYNCREATE(CMyRecordsetWrapper) // protected constructor used by dynamic creation CMyRecordsetWrapper(); CMyRecordsetWrapper(CString filename); // Attributes public: CMyRecordset* myrecordset; long m_index; long m_time; long m_eventtype; CString m_title; long m_binarydataindex; long m_offset; long m_length; // Operations public: void Open(int thetype, LPCTSTR sqlstring, int themode); BOOL IsBOF(); BOOL IsEOF(); void MoveFirst(); void MoveLast(); LONG GetRecordCount(); void Close(); void MoveNext(); BOOL FindNext(LPCTSTR lpszFilter); BOOL FindPrev(LPCTSTR lpszFilter); BOOL CanRestart(); void copyem(); void opentherecordset(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMyRecordsetWrapper) //}}AFX_VIRTUAL // Implementation virtual ~CMyRecordsetWrapper(); protected: // Generated message map functions //{{AFX_MSG(CMyRecordsetWrapper) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CMyRecordsetWrapper::CMyRecordsetWrapper(CString filename) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if (theApp.databaseopen == 0) { AfxDaoInit( ); theApp.eventdatabase = new CDaoDatabase; theApp.eventdatabase->Open(filename); } // increment reference count theApp.databaseopen++; opentherecordset(); } CMyRecordsetWrapper::~CMyRecordsetWrapper() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); delete myrecordset; theApp.databaseopen--; if (theApp.databaseopen == 0) { theApp.eventdatabase->Close(); delete theApp.eventdatabase; AfxDaoTerm(); } } void CMyRecordsetWrapper::opentherecordset() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); myrecordset = new CMyRecordset(theApp.eventdatabase); } void CMyRecordsetWrapper::Close() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); myrecordset->Close(); } void CMyRecordsetWrapper::MoveFirst() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); myrecordset->MoveFirst(); copyem(); } void CMyRecordsetWrapper::copyem() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_index = myrecordset->m_index; m_time = myrecordset->m_time; m_eventtype = myrecordset->m_eventtype; m_title = myrecordset->m_title; m_binarydataindex = myrecordset->m_binarydataindex; m_offset = myrecordset->m_offset; m_length = myrecordset->m_length; }