The MFC database classes found in Visual C++ versions 1.x,
2.x, 4.0, and 4.1 were not written to be used in a console application.
However, with some modification, you can use the 32-bit database classes in a
console application. The techniques presented here apply to both the MFC ODBC
and MFC DAO classes.
Starting with Visual C++ 4.2, the MFC ODBC
classes were rendered safe for use within console applications. Many of the
internal dependencies listed below are no longer present in the 4.2 and later
MFC ODBC class libraries.
Back to the top
Both the MFC ODBC and MFC DAO classes have dependencies
upon non-Database MFC classes, particularly with the existence of a global
CWinApp-derived object. The following list presents these dependencies along
with suggestions for working around them.
For either MFC ODBC or MFC
DAO, it is very important to test your code not only for successful execution,
but for graceful recovery on unexpected conditions (such as the database not
being in an expected path). The majority of the "dependencies" these classes
have on MFC come from error recovery and reporting code within the database
classes.
It is also important to remember that the Visual C++ MFC
database classes released through version 4.1 were not intended or tested for
use in a console application.
Back to the top
Both MFC ODBC and MFC DAO classes
| • | Exception handling
Microsoft recommends that you
wrap exception handling code around each of your calls to an MFC Database class
method. |
| • | Exception handling and resource handles
Internally, MFC ODBC uses AfxThrowDBException to throw exceptions, and MFC DAO
uses AfxThrowDaoException() to throw exceptions. Both functions can result in a
call to CString::LoadString(), which requires a resource handle for the
application. In addition, the MFC DAO method CDaoException::GetErrorMessage(),
used to get more information about a DAO error, also calls
CString::LoadString().
Within CString::LoadString() is a call to
AfxLoadString(), which calls AfxGetResourceHandle(), which expects a valid
resource handle to be defined for the EXE.
To work around this,
define a valid resource handle for your application as shown in this code:
hMod = ::GetModuleHandle( "MyApp.Exe" );
ASSERT( hMod );
AfxSetResourceHandle( hMod );
|
Back to the top
MFC ODBC classes
| • | Use of AfxGetApp() in the MFC ODBC classes
In
synchronous mode when an error is encountered, CDatabase::Open() attempts to
get a pointer to a global CWinApp-derived object and assert if it is not found.
To avoid this, you can do one of the following:| • | Invoke CDatabase::SetSynchronousMode( TRUE ) to disable
asynchronous processing. | | • | Create a global instance of a CWinApp-derived class in
your application similar to the one shown below. This will give you a global
CWinApp object in your console application without actually invoking MFC in any
way.
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance( ) { return FALSE };
};
CMyApp theApp;
| This dependency was removed in Visual C++ 4.2. Use of
Synchronous mode was also removed, as was the OnWaitForDataSource and
InWaitForDataSource methods for both CDatabase and CRecordset. |
| • | Avoiding the need for a valid Windows handle
The
CDatabase::Open() method also attempts to acquire a valid Windows handle to
pass to SQLDriverConnect. If the application using the classes can't provide
one, the GetDesktopWindow method is called. This handle is used by the ODBC API
call SQLDriverConnect as a parent handle to create a dialog if the database
connection information provided is incomplete or inaccurate.
It is
possible to prevent this dialog from being displayed.
For more information about how to do this, click the following article number to view the article in the Microsoft Knowledge Base:
150552 (http://support.microsoft.com/kb/150552/)
How to avoid the ODBC login dialog when using MFC
|
Back to the top
MFC DAO classes
The MFC DAO classes are relatively independent of the
MFC library. However here are some considerations to keep in mind when using
them in a console application:
| • | Use of AfxGetApp() in the MFC DAO classes
The
initialization of a CDaoWorkspace object -- whether explicitly or implicitly by
way of creation of a CDaoDatabase or CDaoRecordset object -- forces a call to
AfxDaoInit(). AfxDaoInit() attempts to ensure that DAO is properly terminated
by setting the m_lpfnDaoTerm member of CWinApp to point to the AfxDaoTerm()
function.
If you do not have a global instance of a CWinApp-derived
class, you need to call AfxDaoTerm() yourself to terminate DAO properly.
For more information about AfxDaoTerm(), click the following article number to view the article in the Microsoft Knowledge Base:
145992 (http://support.microsoft.com/kb/145992/)
Global MFC DAO objects cause assertions
|
Back to the top