📄 vcg14.htm
字号:
}</FONT></PRE>
<P>This code is simple. First you get the name for the new database from the user. If the user cancels the dialog box, you simply do nothing. Otherwise, you close the currently open recordset and the database. Both must be closed to enable the opening of a new database. Next you take the user's new database name (the fully qualified path name) and stuff it into your m_addressesSet.m_DefaultDBName variable. You will use this name when you reopen your database.
<BR>
<P>Once you have a database name saved, you call your recordset's Open() function to do the actual open: m_addressesSet.Open(AFX_DAO_USE_DEFAULT_TYPE). Because you closed the original database, Open() will reopen the database using the database name returned by GetDefaultDBName(). If you had closed only your recordset and not the database, a call to Open() would simply have used the existing, still open, database.
<BR>
<P>Finally, after you've opened the new database, you must update the user interface. You do this by retrieving the current view (a simple process for any SDI application) and call the UpdateData() function with a parameter of FALSE to force an update of the application's data that is being presented to the user. The only thing special about this code is that it shows how to get a pointer to the application's view class from any point in an application:
<BR>
<PRE>
<FONT COLOR="#000080"><B>CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);</B>
<B>CView * pView = pFrame->GetActiveView();</B>
<B>if (pView)</B>
<B>{</B>
<B>// pView is a valid pointer to the view class</B>
<B>}</B>
<B>else</B>
<B>{</B>
<B>// pView is not valid: perhaps we have no view!</B>
<B>}</B></FONT></PRE>
<BLOCKQUOTE>
<BLOCKQUOTE>
<HR ALIGN=CENTER>
<BR>
<NOTE><B>NOTE</B>
<BR>
<BR>You might have noticed that since this application's user interface is specific to the Address database, opening a database with a different table structure (NorthWind.MDB, for example) won't work. It's beyond the purpose of this example to add the complexity required to open and display any database. To test the database open functionality, I've included two versions of the Address database on the CD that comes with this book. These database files are located in the CHAPTR14 folder. The database called Address Book.mdb contains a standard set of five dummy records. The database called Special Address.mdb contains the same five records, but each first name is prefixed with the word SPECIAL.</NOTE>
<BR>
<HR ALIGN=CENTER>
</BLOCKQUOTE></BLOCKQUOTE>
<BR>
<A NAME="E70E69"></A>
<H5 ALIGN=CENTER>
<CENTER>
<FONT SIZE=4 COLOR="#FF0000"><B>Creating a New DAO Access Database</B></FONT></CENTER></H5>
<BR>
<P>A necessary functionality in almost any application is to be able to create a new "document." In the case of a database program, a new document is actually a new database. You could simply not implement this functionality, or you could supply an empty database that the user (or your application) could copy to a new name. This isn't a very elegant solution. It looks kludgy and lacks professionalism. But with ODBC, this was often the way it was done.
<BR>
<BLOCKQUOTE>
<BLOCKQUOTE>
<HR ALIGN=CENTER>
<BR>
<NOTE><B>NOTE</B>
<BR>
<BR>One trick of the trade was to take a new, empty database file and save it as a binary resource in the base application. When the user selected File | New, this binary resource was written out as a disk file and given the name that the user selected. When ODBC didn't provide a way for an application to create an Access database, it was a solution that was invisible to the user. DAO doesn't require you to use these tricks, because you can create an Access database directly.</NOTE>
<BR>
<HR ALIGN=CENTER>
</BLOCKQUOTE></BLOCKQUOTE>
<BLOCKQUOTE>
<BLOCKQUOTE>
<HR ALIGN=CENTER>
<BR>
<NOTE><B>NOTE</B>
<BR>
<BR>Several online documents are available that discuss using DAO to create Access databases. One topic that you can search for in Books Online is "Creating a Database with DAO."</NOTE>
<BR>
<HR ALIGN=CENTER>
</BLOCKQUOTE></BLOCKQUOTE>
<P>To create a new database, follow these steps:
<BR>
<OL>
<LI>Create the basic database.
<BR>
<BR>
<LI>Create a table in your database.
<BR>
<BR>
<LI>Create columns in your table.
<BR>
<BR>
<LI>Create indexes as needed.
<BR>
<BR>
<LI>Repeat steps 2 through 4 as necessary.
<BR>
<BR>
</OL>
<P>You can add a new table to an existing database by following steps 2 through 5. You can add a new column to an existing table in a database by following steps 3 through 5. Here is your sample code:
<BR>
<PRE>
<FONT COLOR="#000080">void CAddressesDoc::OnFileNew()
{
// TODO: Add your command handler code here
<B> // Create a new Access database, then open the doggie!</B>
<B> // First, get a filename to use. Warn if we are overwriting an existing file:</B>
<B> CFileDialog dlg(FALSE,</B>
<B> NULL,</B>
<B> "*.mdb",</B>
<B> OFN_OVERWRITEPROMPT,</B>
<B> "Access Database Files (*.mdb) | *.mdb | "</B>
<B> "All Files (*.*) | *.* ||");</B>
<B> if (dlg.DoModal())</B>
<B> {// User did not cancel the open file dialog:</B>
<B> TRACE("File selected is '%s'\n", dlg.GetPathName());</B>
<B> // Close the existing database (if open):</B>
<B> if (m_addressesSet.IsOpen())</B>
<B> {// If open (avoid errors and crashes!), then close:</B>
<B> m_addressesSet.Close();</B>
<B> if (m_addressesSet.m_pDatabase != NULL)</B>
<B> {// Close the DB too. If not closed, old DB is reopened!</B>
<B> m_addressesSet.m_pDatabase->Close();</B>
<B> }</B>
<B> }</B>
<B> // Create, create, it's off to create we go!</B>
<B> // Notice: we are using CDaoDatabase's Create() function.</B>
<B> m_addressesSet.m_DefaultDBName = dlg.GetPathName();</B>
<B> if (m_addressesSet.m_pDatabase != NULL)</B>
<B> {// We are stuffed if m_pDatabase is NULL!</B>
<B> m_addressesSet.m_pDatabase->Create(</B>
<B> m_addressesSet.m_DefaultDBName,</B>
<B> dbLangGeneral,</B>
<B> dbVersion30);</B>
<B> // Define the table (connected to our database)...</B>
<B> CDaoTableDef TableDef(m_addressesSet.m_pDatabase);</B>
<B> TableDef.Create(_T("Addresses"));</B>
<B> // Define columns (hard-code them):</B>
<B> TableDef.CreateField(_T("AddressID"),</B>
<B> dbLong, 4, dbAutoIncrField);</B>
<B> TableDef.CreateField(_T("FirstName"),</B>
<B> dbText, 50, dbVariableField);</B>
<B> TableDef.CreateField(_T("LastName"),</B>
<B> dbText, 50, dbVariableField);</B>
<B> TableDef.CreateField(_T("SpouseName"),</B>
<B> dbText, 50, dbVariableField);</B>
<B> TableDef.CreateField(_T("Address"),</B>
<B> dbText, 255, dbVariableField);</B>
<B> TableDef.CreateField(_T("City"),</B>
<B> dbText, 50, dbVariableField);</B>
<B> TableDef.CreateField(_T("StateOrProvince"),</B>
<B> dbText, 20, dbVariableField);</B>
<B> TableDef.CreateField(_T("PostalCode"),</B>
<B> dbText, 20, dbVariableField);</B>
<B> TableDef.CreateField(_T("Country"),</B>
<B> dbText, 50, dbVariableField);</B>
<B> TableDef.CreateField(_T("EmailAddress"),</B>
<B> dbText, 50, dbVariableField);</B>
<B> TableDef.CreateField(_T("HomePhone"),</B>
<B> dbText, 30, dbVariableField);</B>
<B> TableDef.CreateField(_T("WorkPhone"),</B>
<B> dbText, 30, dbVariableField);</B>
<B> TableDef.CreateField(_T("WorkExtension"),</B>
<B> dbText, 20, dbVariableField);</B>
<B> TableDef.CreateField(_T("MobilePhone"),</B>
<B> dbText, 30, dbVariableField);</B>
<B> TableDef.CreateField(_T("FaxNumber"),</B>
<B> dbText, 30, dbVariableField);</B>
<B> TableDef.CreateField(_T("Birthdate"),</B>
<B> dbDate, 8, dbFixedField);</B>
<B> TableDef.CreateField(_T("SendCard"),</B>
<B> dbBoolean, 1, dbVariableField);</B>
<B> TableDef.CreateField(_T("Nickname"),</B>
<B> dbText, 30, dbVariableField);</B>
<B> TableDef.CreateField(_T("Notes"),</B>
<B> dbMemo, 0, dbVariableField);</B>
<B> TableDef.CreateField(_T("Hobbies"),</B>
<B> dbText, 255, dbVariableField);</B>
<B> TableDef.Append();</B>
<B> // Close the database, then reopen it using the CDaoRecordset class</B>
<B> m_addressesSet.m_pDatabase->Close();</B>
<B> m_addressesSet.Open(AFX_DAO_USE_DEFAULT_TYPE);</B>
<B> // Refresh the view to reflect the *new* database's data:</B>
<B> CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd);</B>
<B> CView * pView = pFrame->GetActiveView();</B>
<B> if (pView)</B>
<B> {</B>
<B> pView->UpdateData(FALSE);</B>
<B> }</B>
<B> }</B>
<B> }</B>
}</FONT></PRE>
<P>As in other listings, the code added manually appears in bold. Notice the sequence of events:
<BR>
<OL>
<LI>Create the database (you have already saved the database name in the m_defaultDBName member variable). An alternative to using m_defaultDBName would be to use a call to GetDefaultDBName() to return the correct name.
<BR>
<BR>
<PRE>
<FONT COLOR="#000080"><B>m_addressesSet.m_pDatabase->Create(</B>
<B> m_addressesSet.m_DefaultDBName,</B>
<B> dbLangGeneral,</B>
<B> dbVersion30);</B></FONT></PRE>
<LI>Create the table (using a CDaoTableDef object):
<BR>
<BR>
<PRE>
<FONT COLOR="#000080"><B>CDaoTableDef TableDef(m_addressesSet.m_pDatabase);</B>
<B> TableDef.Create(_T("Addresses"));</B></FONT></PRE>
Create one table (and its fields) at a time.
<BR>
<BR>
<LI>Create the table's columns (fields):
<BR>
<BR>
<PRE>
<FONT COLOR="#000080"><B>TableDef.CreateField(_T("AddressID"),</B>
<B> dbLong, 4, dbAutoIncrField);</B>
<B>TableDef.CreateField(_T("FirstName"),</B>
<B> dbText, 50, dbVariableField);</B></FONT></PRE>
This code shows only two fields, but the sample program actually creates 19 columns (called fields) in the table.
<BR>
<BR>
<LI>Save the database's table definition:
<BR>
<BR>
<PRE>
<FONT COLOR="#000080"><B>TableDef.Append();</B></FONT></PRE></UL></UL>
Each table must be saved using the Append() member function.
<BR>
<BR>
</OL>
<P>After you've created the database, tables, and table columns, you can close the database and reopen it. Although it's not strictly necessary to close a database after creating it, it makes sense to start off from a known state—freshly opened.
<BR>
<P>If you've been working along with this book, you now can create a database and open it. Here lies the wrinkle: Your application can open a database, but there is no provision to add new records! This shortcoming rather limits the program's usefulness. The next step is to create code to add records to the database.
<BR>
<BR>
<A NAME="E70E70"></A>
<H5 ALIGN=CENTER>
<CENTER>
<FONT SIZE=4 COLOR="#FF0000"><B>Adding Indexes to a DAO Database</B></FONT></CENTER></H5>
<BR>
<P>After you've created the database's tables and columns, you should also create any indexes your application will need. Although it's not strictly necessary to have indexes in a database, they can greatly enhance performance.
<BR>
<P>In the example, you will index the same columns that Microsoft did when Access's Database Wizard created your template database. Here are the indexes and the columns used by the indexes:
<BR>
<UL>
<UL>
<P>PrimaryKey using the field AddressID, which will be the primary key
<BR>
</UL></UL>
<UL>
<UL>
<P>EmailAddress using the field EmailAddress
<BR>
</UL></UL>
<UL>
<UL>
<P>LastName using the field LastName
<BR>
</UL></UL>
<BLOCKQUOTE>
<BLOCKQUOTE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -