📄 ch09.htm
字号:
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Much of the functionality of <TT>TField</TT>
can be achieved with visual tools. In particular, you can manipulate fields with
the Fields
Editor, which you can access by clicking once with the right mouse button
on the top of a <TT>TTable</TT> or <TT>TQuery</TT> object. This subject is explored
in more depth in Chapter 9. However, good programmers know how to use both the methods
of
<TT>TDataSet</TT> and the Fields Editor. Furthermore, the Fields Editor can be
used to best advantage if you understand how to enhance its functionality with some
of the code you are learning about in this chapter.
<HR>
</BLOCKQUOTE>
<P>In this
section and the one previous to it you learned how to access the fields
of a record. In the next section you will see how to use this knowledge when you
want to append, insert, or edit records in a dataset.
<H3><A NAME="Heading18"></A><FONT
COLOR="#000077">Changing Data</FONT></H3>
<P>The following methods enable you to change the data associated with a table:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall Post(void);
void __fastcall Insert(void);
void __fastcall Edit(void);
void
__fastcall Append(void);
void __fastcall Delete(void);
void __fastcall Cancel(void);
</FONT></PRE>
<P>All these routines are part of <TT>TDataSet</TT>, and they are inherited and used
frequently by <TT>TTable</TT> and <TT>TQuery</TT>.</P>
<P>The
preceding list is hardly exhaustive. For instance, here are a few more related
methods of <TT>TDataSet</TT>:</P>
<PRE><FONT COLOR="#0066FF"> void __fastcall AppendRecord(const TVarRec *Values, const System::Integer
Values_Size);
void __fastcall ClearFields(void);
void __fastcall InsertRecord(const TVarRec *Values, const System::Integer Values_Size);
void __fastcall FetchAll(void);
void __fastcall UpdateRecord(void);
void
__fastcall ApplyUpdates(void);
void __fastcall CommitUpdates(void);
void __fastcall CancelUpdates(void);
</FONT></PRE>
<P>The point here is not that you need to learn all these methods right away. Rather,
I would concentrate on the first list, the
one that include <TT>Post</TT>, <TT>Insert</TT>,
and so on. This first list is meant to be a fairly careful selection of the most
commonly used methods. Many programmers will never need to use any other methods
than those in the first list. But it is
helpful to know that the <TT>TDataSet</TT>
object has considerable depth, and if you need customized functionality, you can
generally find it in the <TT>TDataSet</TT> object itself.
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT
COLOR="#000077"><B>NOTE:</B></FONT><B> </B>There are, of course, times when
some programmers might need to do something to a database that is not covered in
the VCL. In those cases, your next resort after <TT>TDataSet</TT> might well be the
BDE
itself. In particular, you should use the Borland Database Engine, found in <TT>BDE.HPP</TT>,
or in a separate package available from Borland.
<HR>
</BLOCKQUOTE>
<P>Whenever you want to change the data associated with a record, you must first
put
the dataset you are using into edit mode. As you will see, most of the visual
controls do this automatically. However, if you want to change a table programmatically,
you need to use the functions listed previously.</P>
<P>Here is a typical sequence
you might use to change a field of a given record:</P>
<PRE><FONT COLOR="#0066FF">Table1->Edit();
Table1->FieldByName("ShipToContact")->Value = "Lyle Mayes";
Table1->Post();
</FONT></PRE>
<P>The first line shown
places the database in edit mode. The next line assigns the
string <TT>"Lyle Mayes"</TT> to the field labeled <TT>"ShipToContact"</TT>.
Finally, the data is written to disk when you call <TT>Post</TT>. See the SimpleEdit
program on
the CD-ROM accompanying this book for an example of this code in action.
When looking at that programming, you might note that I have double-clicked the grid
control in order to edit its properties. Working with the grid control will be explained
in
more depth later in this chapter.</P>
<P>The very act of moving on to the next record automatically posts your data to
disk. For instance, the following code has the same effect as the code shown previously,
plus it moves you on to the next
record:</P>
<PRE><FONT COLOR="#0066FF">Table1->Edit();
Table1->FieldByName("ShipToContact")->Value = "Lyle Mayes";
Table->Next();
</FONT></PRE>
<P>Calls to <TT>First</TT>, <TT>Next</TT>, <TT>Prior</TT>, and
<TT>Last</TT> all
perform <TT>Post</TT>s, as long as you are in edit mode. If you are working with
server data and transactions, the rules explained here do not apply. However, transactions
are a separate matter with their own special rules, as
explained in Chapter 15, "Working
with the Local InterBase Server." (Both local tables and SQL servers support
transactions, but I cover this subject in the chapter on the InterBase server because
it is usually considered an intermediate or
advanced database topic.)</P>
<P>Even if you are not working with transactions, you can still undo your work at
any time, as long as you have not yet either directly or indirectly called <TT>Post</TT>.
For instance, if you have put a table into edit
mode, and have changed the data in
one or more fields, you can always change the record back to its original state by
calling <TT>Cancel</TT>. For instance, you can edit every field of a record, and
then call the following line to return to the state
you were in before you began
editing:</P>
<PRE><FONT COLOR="#0066FF">Table->Cancel();
</FONT></PRE>
<P>Here is an excerpt from the SimpleEdit program that shows three button response
methods that enable you to enter data and then cancel or post
your changes. This
code is still not robust enough for a shipping programming, but it gives you a good
idea of how to proceed if you don't want to include much error checking.</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::bEditClick(TObject
*Sender)
{
AnsiString S;
if (InputQuery("Enter Contact Dialog", "Enter Name", S))
{
DMod->tblOrders->Edit();
DMod->tblOrders->FieldByName("ShipToContact")->Value = S;
}
}
void
__fastcall TForm1::bCancelClick(TObject *Sender)
{
DMod->tblOrders->Cancel();
}
void __fastcall TForm1::bPostClick(TObject *Sender)
{
DMod->tblOrders->Post();
}
</FONT></PRE>
<P>I say this code is not really robust. For
instance, I do not check to see if the
dataset is in edit or insert mode before calling <TT>Post</TT>. This kind of error
checking is covered later in this chapter, and several times in the next few chapters.
Despite its lack of error checking, the
simple methods shown here should give you
a good idea of how to proceed in your own programs.
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The <TT>InputQuery</TT> method shown
in the
<TT>bEditClick</TT> method is used to retrieve a string from the user. The
first parameter is the title of the dialog used to retrieve the string, the second
the prompt asking for a string, and the third the string to be retrieved.
<TT>InputQuery</TT>
is a Boolean VCL function. It is usually best to zero out the string passed in the
third parameter before showing it to the user.
<HR>
</BLOCKQUOTE>
<P>There are also cancel, edit, and insert buttons on the
<TT>TDBNavigator</TT> control.
You can use this control to work with a dataset without having to write any code.</P>
<P>There are two methods, called <TT>Append</TT> and <TT>Insert</TT>, which you can
use whenever you want to add another record to a
dataset. It obviously makes more
sense to use <TT>Append</TT> on datasets that are not indexed, but BCB won't throw
an exception if you use it on an indexed dataset. In fact, it is always safe to use
either <TT>Append</TT> or <TT>Insert</TT> whenever
you are working with a valid dataset.</P>
<P>On your disk you will find a simple program called Inserts, which shows how to
use the <TT>Insert</TT> and <TT>Delete</TT> commands. To create the program by hand,
first use a <TT>TTable</TT>,
<TT>TDataSource</TT>, and <TT>TDBGrid</TT> to open up
the <TT>COUNTRY</TT> table from the demos subdirectory. Then place two buttons on
the program's form and call them Insert and Delete. When you are done, you should
have a program like the one shown
in Figure 9.5.<BR>
<BR>
<A NAME="Heading21"></A><A HREF="09ebu05.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/09/09ebu05.jpg">FIGURE 9.5.</A><I>The Inserts
program knows how to insert and delete a record from the <TT>COUNTRY</TT> table.</I>
<DL>
<DD>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT
COLOR="#000077"><B>NOTE:</B></FONT><B> </B>To spice up the Inserts program,
you can drop a panel on the top of the form and then add the buttons to the panel.
Set the panel's <TT>Align</TT> property to <TT>alTop</TT>, and set the <TT>TDBGrid</TT>'s
<TT>Align</TT> property to <TT>alClient</TT>. If you run the program, you can then
maximize and resize the form without damaging the relationship between the various
visual components.
<HR>
</BLOCKQUOTE>
<P>The next step is to associate code
with the Insert button:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::FInsertClick(TObject *Sender)
{
FCountry->Insert();
FCountry->FieldByName("Name")->Value = "Erehwon";
FCountry->FieldByName("Capital")->Value = "Nowhere";
FCountry->FieldByName("Continent")->Value = "Imagination";
FCountry->FieldByName("Area")->Value = 0;
FCountry->FieldByName("Population")->Value = 0;
FCountry->Post();
}
</FONT></PRE>
<P>The function shown here first puts the table into insert mode, which means that
a new record filled with blank fields is automatically
inserted into the current
position of the dataset.</P>
<P>After inserting the record, the next job is to assign strings to one or more of
its fields. There are, of course, several different ways to enter this data. Using
the current program, you could
simply type the information into the current record
in the grid. Or, if you wanted, you could place standard edit controls on the form
and then set each field equal to the value the user has typed into the edit control:</P>
<PRE><FONT
COLOR="#0066FF">Table1->FieldByName(`Name')->Value = Edit1.Text;
</FONT></PRE>
<P>If you place a table in edit mode, or if its <TT>TDataSource</TT> object has <TT>AutoEdit</TT>
set to <TT>True</TT>, you can use data-aware controls to insert
information directly
into a record.</P>
<P>The intent of this chapter, however, is to show you how to enter data programmatically.
Therefore you are presented with an example in which information is hardwired into
the code segment of the program:</P>
<PRE><FONT COLOR="#0066FF">FCountry->FieldByName("Name")->Value = "Erehwon";
</FONT></PRE>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>One of the interesting (or perhaps
"frustrating"
would be a more appropriate word) byproducts of this technique
is that pressing the Insert button twice in a row automatically triggers a "Key
Violation" exception. To remedy this situation, you must either delete the current
record or
manually change the <TT>Name</TT> and <TT>Capital</TT> fields of the newly
created record. <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -