Click here to Skip to main content
15,904,934 members
Articles / Desktop Programming / MFC
Article

DAO ClassWizard for Visual Studio .NET

Rate me:
Please Sign up or sign in to vote.
2.80/5 (5 votes)
8 Feb 200310 min read 83.2K   635   12   7
Create and maintain CDAORecordset classes for MS Access Tables in Visual Studio .NET


What this is?

This is anadd-on for Vsual Studio .NET C++ developers and it helps you in creating and maintaining CDaoRecordset classes. CDaoRecordset classes are normally used to work with Microsoft Access Tables. Since Microsoft has removed its original DAO ClassWizard in Visual Studio .NET, which you may know from former VStudio releases (6.0 for example), one had to manually add and maintain CDaoRecordsets, field-variables and all the other stuff in .NET. Now you can use this Wizard to work with your Access Databases again. This wizard is also highly configurable. You can customize the style and some basic functionality for new classes and use custom DFX-Routines, data-types and variable initializers.

Why it is there?

When I switched from Visual Studio 6.0 to .NET, I had to continue on a large project that used over 100 Microsoft Access tables and only the half of the tables have been finished and connected to CDaoRecordset clases. I wanted to use some of the new features of Visual Studio .NET and MFC 7.0. This is why I continued the project in .NET instead of in Visual Studio 6.0. The project uses non-default DFX-Routines and custom data-types. Also, the base-class for new table-classes was not CDaoRecordset but CIBTable instead. (The original wizard creates only classes directly derived from CDaoRecordset). With the old original DAO ClassWizard, I had to rename all type-identifiers for member-variables manually, adjust the DFX-calls manually, add additional include-files manually, adjust the constructor parameters and base-classes manually. And now, within .NET, I even had to create the classes manually. I wanted the DAO ClassWizard back!. And because there was none, I decided to develop this one.

Source-Code and functionality

This program was written in a hurry, so expect bugs. The source-code is not included because it´s a mess and reading into it as a third person will be a pain. If you find bugs or something missing, contact me at drice@ageone.de and I may implement or fix it. However, you can request the source-code if you really want it.

Using the DAOClassWizard

The DAOClassWizard can only be used with C++ projects, not with C# or other kinds of languages. Your solution which you have loaded in the Visual-Studio .NET IDE can contain C# or other projects, but it must contain at least one C++ project.

To use the wizard, start the Visual Studio NET IDE and load a C++ project, then run DAOClassWizard.exe. The wizard will automatically connect to your Visual Studio .NET IDE and query for information about the loaded solution. When you run the wizard, you´ll see a dialog containing some combo-boxes, buttons and a large listview at the bottom.

At the top of thedialog, there are two input-lines. The first, grayed one, is the name (full path) of the database which is currenly loaded. The second one is a combo-box which lists all the available tables in the database.

Below the database fields is another group-box with two combo-boxes. The upper one contains all your projects in the current solution. The second contains the available classes in the selected project. Note that only classes that deal with recordsets (tables) are contained in the classes combo-box. Other classes are not displayed.

The "Bindings" listview lists the member-variables of the selected class and the fields of the selected database to which the member-variables are bound. Note that the term "member variables" refers only to those variables which are included in the //{{AFX_FIELD ... //}}AFX_FIELD comment-block in the class declaration.

The listview has four columns, named DB.Field , DB.Type, C++ Type and C++ Variable Identifier. The first column contains the original names of the fields of the selected table. The DB.Type column lists the corresponding database-types. The third column contains the C++ Type identifier (i.e. long, CString...) and the fourth column lists the variable identifier (i.e. m_dwMyValue1...).

Depending on the table and class you´ve selected, the listview will show multiple rows. Each row refers to one member variable and/or table field.

If a table contains a field named FIELD1 but there is no class variable bound to this field, the columns C++ Type and C++ Variable identifier are empty. If there is a member variable with no field bound to it, the DB.Field and DB.Type columns are empty.

DAOClassWizard uses the contents of the //{{AFX_FIELD_MAP ... //}}AFX_FIELD_MAP comment block in your .CPP files find out which field is bound to which variable.

Adding, Renaming and deleting variables

First select the table and class you wish to work with. To add, rename or remove a variable, select an item in the “bindings” listview, click the right mouse- button and select a command from the context-menu that appears. When you click “add variable” a dialog-box appears and DAOClassWizard suggests a C++ Type and variable identifier which you can modify.

You can configure the C++ Type that should be suggested for a specific field type. For example, if you add a variable for a field “UserName” which is a TEXT-Type-Field, the wizard suggests CString as Type-Identifier and m_csUserName as variable-name. The type CString and the variable prefix m_cs can be configured.

Adding a new class for a table

To add a new class for a table, select a table first and then click "Create Class". The wizard will suggest a name for the class and the filenames in which the class should be declared / implemented. You can change the classname and the names of the files.

In the dialog that appears, click "OK" to create the class. Note that no files are created at this time and that no items are added to your Visual Studio Project. The files for new classes are created and added to the project, when you click the "Ok / Apply changes" button in the main-dialog.

Configuring DAOClassWizard

As you may have noticed, there is a menu called “Setup” in the top-left corner of the DAOClassWizard dialog. There are two commands “Class Creation Options” and “Database / C++ Type settings”.

Class Creation Options

You can use the class creation options to modify the style how new classes are created by DAOClassWizard. The “Class Creation Options” dialog box has several fields which are explained below:

New Class Prefix, Suffix, Parameters, Base Class Name and Initialization-String

When you create new Classes with DAOClassWizard, the wizard suggests a name for the new class. You can configure this suggestion with the fields "New Class Prefix" and "Suffix". The suggested class-name will be constructed in the following way

<prefix>+<TableName>+<Suffix></code>

So, if your table is named Employees, the prefix is C and the suffix is Table, the suggested class name will be CEmployeesTable. You can modify this name at class-creation time in another dialog-box. These settings here are only there to help you speed up the process.

As you may know, most classes are derived from a base-class. The name of this base-class can be specified in the field "Base Class Name". Typically you enter the string CDaoRecordset into this field. Continuing with our employees example, the class declaration will then look like this:

class CEmployeesTable : CDaoRecorsdset {

If you leave the "Base Class Name" field empty, the class declaration will be

class CEmployeesTable {

Each class you create does have a constructor. This constructor is declared in the .H file and implemented in the .CPP file. Constructors can have parameters and the base class could be initialized with these parameters. Use the fields "New class Parameters" and "Base Class Initialization String" to modify this behaviour: The constructor-declaration for the new class will be created in the following way:

<classname>+"("+<parameters>+")"

So, if you enter the string CDaoDatabase *pDB in the Parameters field, the constructor declaration in the .H file will look like this.

CEmployeesTable(CDaoDatabase *pDB) {

To initialize the base-class, enter the whole parameter-string into "base class initialization", like (pDB). The implementation of the constructor will then look like this:

CEmployeesTable::CEmployeesTable(CDaoDatabase *pDB) : public CDaoRecordset(pDB) {<BR>};

If you leave the "base class initialization string empty", the constructor will be:

CEmployeesTable::CEmployeesTable(CDaoDatabase *pDB) {<BR>};

Indention

When the code for a new class is created, you can control the indention of code lines. With Scope-modifier indention, you can control the indention of keywords like private, public... With AFX_FIELD-block indention you can control the indention of the other code. I don´t want to explain this in detail here, just give it a try.

Additional file contents

When the wizard creates the files for your new class, you can specify additional code that should be inserted at the beginning of the files. Typically you enter your #include preprocessor statements here. The default is #include "stdafx.h".

Database / C++ Type settings

When you activate this command, a dialog box with a grid (it´s Chris Maunder's MFCGridControl) appears. The grid contains 30 rows and 5 column headers named DB.Type, C++ Type, Var.Prefix, Initializer and DFX-Routine. When the wizard creates code or suggests anything (like type identifiers, variable names, ...) it looks up this table.

When the wizard suggests a name for a variable or type identifier for you, it looks up the field-type of the database- field in the grid and then takes the C++ type identifier and variable prefix from the apropriate row and applies it to the suggestion.

For example, if you activate the command (in the bindings-listview) "Add Variable" for a MEMO-type database field, which we name Notes , the wizard knows that this field is of the type dbMemo. It then looks up the string dbMemo in the grid, takes the C++ type- and variable-identifier prefix from the discovered row and suggests CString as type identifier and m_csNotes as variable identifier.

When the wizard creates a new class, it must create code. This code consists mainly of three sections which are enclosed in comment blocks. You may already know of what I´m speaking now. The //{{AFX_FIELD comments.

These sections have a starting comments like //{{AFX_FIELD, //{{AFX_FIELD_INIT and //{{AFX_FIELD_MAP and corresponding ending comments like //}}AFX_FIELD, //}}AFX_FIELD_INIT and //}}AFX_FIELD_MAP. The lines between these comments is the code that the wizard maintains.

The //AFX_FIELD block is contained in the .H file and contains the variable declrations, the //AFX_FIELD_INIT and //AFX_FIELD_MAP blocks are located in the .CPP file. The //AFX_FIELD_INIT field is located within the constructor of the class and is used to initialize the variables to default values when the class is initiated. An //AFX_FIELD_INIT section may look like this

//{{AFX_FIELD_INIT(CEmployeesTable)<BR>m_csFirstName = _T("");<BR>m_csLastName = _T("");<BR>m_dtBirthday = COleDateTime(0);<BR>m_fSalary = 0.0;<BR>//}}AFX_FIELD_INIT<BR>

The initializers (at the right side of the assignment operator =) are taken from the grids Initializer Column. When the wizard writes the code for this section, it looks up the C++ type-identifier in the grid (C++ Type column) and uses the Initializer in the discovered row.

For example, if you have a Table with a field named FirstName, which is a TEXT (dbText)-type field and you have bound the variable CString m_csFirstName to that field, the wizard looks up CString in the grid, then takes the initializer, which is _T("") by default for CString, and writes out m_csFirstName = _T("");

If the Initializer-string in the grid is left empty, the variable will not be initialized in the //AFX_FIELD_INIT section.

Some variables (instances of classes) cannot be assigned a value or must be initialized by calling a method of the class. If the initializer-string in the grid begins with a period (.) the wizard does not write an assignment, but it writes a method call.

For example, if you replace the Initializer _T("") in the CString-row with .Empty(), the wizard creates the code m_csFirstName.Empty(); instead of m_csFirstName = _T("");

The //AFX_FIELD_MAP section is used to do the data-exchange between the member variables of the class and the database fields. There are several standard DFX-routines provided by MFC, but you can also write your own, custom DFX-routines (refer to the MSDN-Library for more information on how to write custom DFX-routines).

Again, when the wizard writes the code for this section, it looks up the C++ data-type for a member-variable in the grid and uses the apropriate DFX-routine.

For example, if you have again the variable CString m_csFirstName, the wizard looks up CString in the grid, finds the DFX-Routine DFX_Text and writes out the code

DFX_Text(pFX, _T("[FirstName]"), m_csFirstName);

Resetting the configuration

If you want to get the default configuration of the wizard, exit the wizard, open the registry-editor, go to HKEY_CURRENT_USER\Software\BluePearl and delete the DAOClassWizard key there. Then restart DAOClassWizard.

Conclusion

Well, that´s it ! If you have any questions or comments, contact me at drice@ageone.de

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) BluePearl Software
Germany Germany
I started in the late 80´s with a VIC 20 and wrote my first computer programs. In the 1990´s I developed games for a published diskmag and also became active in the demo-scene. That was the time where I got a deep unserstanding about computers, Bits and Bytes and programemd alot of different things (Games, Compilers, Tools and Alot of other stuff - It was just pure Fun !). In that Time I was also reading alot of books. I´ve used Turbo Pascal, Assembler, C++ and finally arrived in the business and C# world. In 2001 I founded my own company "BluePearl Software" and I develop business and technical applications for small and mid-sized companies as a freelancer, both industrial and non-industrial and in a wide range of business sectors.

I am still interested in the nitty-gritty of PCs and software and how to code/design software in an elegant way. I like to face and solve problems and design good software.

Comments and Discussions

 
General&quot;Could not initialize VStudio DTE Manager&quot;... Pin
nmg6-Oct-04 19:01
nmg6-Oct-04 19:01 
GeneralRe: &quot;Could not initialize VStudio DTE Manager&quot;... Pin
JohnKibler28-Nov-04 6:20
JohnKibler28-Nov-04 6:20 
GeneralWrong location Pin
fifi9-Feb-03 4:51
fifi9-Feb-03 4:51 
GeneralRe: Wrong location Pin
krism4217-Oct-05 14:21
krism4217-Oct-05 14:21 
Generalexecution error Pin
scott sanders19-Jan-03 15:56
scott sanders19-Jan-03 15:56 
I tried running your program on both my XP machines, and get the same error (doesn't matter if VS.Net IDE is running or not) :

This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.

When I look in the event log, two entries are generated in the System log :

Event Type: Error
Event Source: SideBySide
Event Category: None
Event ID: 59
Description:
Generate Activation Context failed for C:\tmp\daoclasswizard.exe. Reference error message: The operation completed successfully.

Event Type: Error
Event Source: SideBySide
Event Category: None
Event ID: 58
Description:
Syntax error in manifest or policy file "C:\tmp\daoclasswizard.exe" on line 0.


Any suggestions ?

thanks
srs

GeneralRe: execution error Pin
mrfreezie6-Feb-03 12:53
mrfreezie6-Feb-03 12:53 
GeneralRe: execution error Pin
drice8-Feb-03 23:02
drice8-Feb-03 23:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.