Chapter 11 TClientDataSet is the same as TTable, TQuery, and TclientDataSet is also inherited from TDataSet, which is usually used for clients of multi-layer architectures. TclientDataSet's biggest feature is that it does not rely on BDE (Borland Database Engine), but it requires a dynamic link library support, this dynamic link library called dbclient.dll. On the client, you don't need to use the TDATABASE component because the client is not directly connected to the database.
Since TclientDataSet is inherited from TDataSet, it supports functions such as editing, search, browsing, error correction, filtering. Since the TclientDataSet establishes the local copy of the data in memory, the above-described operation is very fast. It is also because TclientDataSet does not directly connect to the database, so the client must provide a mechanism for obtaining data. In Delphi 4, TclientDataSet has three ways to get data:
Access data from the file.
Get data from another data set from the local.
Get data from the remote database server via the iProvider interface.
In a client program, you can use the above three mechanisms to obtain data.
11.1 Browse and edit data
Like other data sets, the data sets introduced by TclientDataSet can be displayed with standard data controls, of course, this requires the TDataSource component.
Since TClientDataSet is inherited from TDataSet, the TclientDataSet components are also roughly available in the functions supported from TDataSet. Different, TclientDataSet can establish a copy of the data in memory, so TclientDataSet adds some special functions than other data set components.
11.1.1 Browsing Data
The data set introduced by TclientDataSet can be displayed with a standard data control. In the runtime, functions such as First, GotoKey, Last, Next, and Prior can be called to browse the data.
TclientDataSet also supports bookmarking features, you can use bookmarks to mark a record, and you can easily find this record.
For data set components such as TTABLE, TQuery, only the recno attribute can only determine the number of the current record. For the TclientDataSet component, you can also write the RecNo property, making the record of a number of serials becomes the current record.
11.1.2 CANMODIFY properties
TDataSet's CANMODIFY attribute is used to determine if the data in the data set can be modified. The CANMODIFY property itself is read-only, that is, the data can be modified does not depend on the application.
However, the TclientDataSet component has its own specialty because TclientDataSet has created a copy of the data in memory, so the application can decide whether to modify the data. If the user is not allowed to modify the data, simply set the ReadOnly property to True. At this point, the CANMODIFY attribute will definitely return false.
Unlike other data set components, modify the ReadOnly property of the TclientDataSet component, do not need to set the Active property to True in advance.
11.1.3 Cancellation
The basic unit of TclientDataSet transfer data is called a packet, and the current packet can be accessed by the DATA property. However, the user's modification of the data is not directly reflected in the Data property, but is temporarily written to a Delta property, which is the advantage of being able to cancel the modification at any time.
However, here will explain that although users' modifications are not reflected to Data, it is the latest modified data in the data control in the data control. If a record has been repeatedly modified many times, the user sees only the latest data, but the log is recorded many times. To cancel the last modification, call the undolastChange function. UndolastChange needs to pass a Boolean type parameter called FollowChange, if the FOLLOWCHANGE parameter is set to true, the cursor is moved to the recovered record, and if the FOLLOWCHANGE parameter is set to false, the cursor is still on the current record.
ChangeCount Attributes Returns the number of modifications recorded in the log. If a record is repeatedly modified multiple times, each calling of the undolastchange will cancel the last modification step by step.
UndolastChange can only cancel the last changes, if you want to cancel all modifications, first select a record, then call RevertRecord. RevertRecord will cancel all changes to the current record from the log.
TclientDataSet also has a SavePoint property that saves the current editing state and can return the status at the time later. For example, you can save the current state:
BeforeChanges: = ClientDataSet1.savePoint;
In the future, it can be restored to the status of the time:
ClientDataSet1.savePoint: = Beforchanges;
The application can save multiple states, which can restore one of the states, however, once a state is restored, the state after it is invalid.
If you want to cancel all modifications recorded in the log, you can call the CanceElupdates function. Cancelupdates will clear the log and cancel all modifications.
If the Logchanges property is set to false, the user's modification of the user is directly reflected in the DATA property.
11.1.4 Combined modification
To merge the modifications recorded in the log into the DATA property, there are two ways, which way specifically used, depends on the mechanism of the application acquisition data. However, no matter which mechanism, the log is automatically emptied.
For a program that gets data from a file, simply call the MergeChangeLog function, incorporate the modifications recorded in the log into the DATA property. Don't worry that other users have modified data at the same time.
For a program that acquires data from the application server, you cannot call MergeChangeLog to merge data, and call the ApplyUpdates function, Applyupdates will pass the modifications recorded in the log to the application server, and the application server has updated the data to the database server. Will be merged into the DATA property.
11.1.5 Correction
TclientDataSet supports error correction. In general, it is necessary to establish an error correction rule to correct the data input by the user.
Also, if you get an iProvider interface, you can also introduce the error correction rule from the remote server.
Sometimes, the client may need to temporarily prohibit error correction, because the client retrieved data from the application server is phased, and some error correction rules are likely to report.
To temporarily prohibit error correction, you can call DisableConstraints. To re-enable error correction, you can call the EnableConstraints function. DisableConstraints and EnableConstRAINTS are actually a count for an internal.
11.2 index
Use indexes have such a few benefits:
The positioning record is faster in the data set. . You can create a Lookup or Master / Detail relationship between two datasets.
You can sort records.
In the multilayer architecture, when the client retrieves data from the application server, it has obtained the default index. The default index is called Default_order, you can use this index, but you cannot modify or delete this index.
In addition to the default index, TClientDataSet also automatically creates a sub-index called ChangeIndex on the records recorded in the log. Like Default_order, this sub-index cannot be modified or deleted.
In addition, you can use other indexes established in the data set, or build an index yourself.
11.2.1 Creating a new index
To create a new index, you can call AddIndex. AddIndex needs to pass several parameters:
First, the name parameter is used to specify an index name. The name of the index is required when the index is running switching index.
The second is the fields parameter, which is a string that specifies the field name in the index, separated from each other.
The third is the options for setting the index, including the ixdescending element indicates in descending order, including the IXCaseInSensitive element indicates that case is not sensitive.
The fourth is the descfields parameter, which is also a string that specifies several field names, which will be arranged in descending order.
5 is the caseinsfields parameter, its role is similar to the Descfields parameter, which is included in the field in the CaseinsFields parameter.
Sixth is the GroupingLevel parameter, used to specify the packet level, its value cannot exceed the number of fields in the index.
The following code creates an index:
If Edit1.Text <> '' and clientdatanet1.fields.Findfield (Edit1.Text) THEN
Begin
ClientDataSet1.AddIndex (Edit1.Text 'Index', Edit1.Text,
[ixcaseinsensitive], '', '', 0);
ClientDataSet1.indexName: = Edit1.Text 'Index'
END;
To avoid creating an index, you can temporarily use the indexfieldNames property to specify a number of fields, let the dataset are sorted by these fields.
11.2.2 Delete and switch index
To delete a previously created index, you can call DELETEINDEX and specify the index name to be deleted. Note: DEFAULT_ORDER and CHANGEINDEX cannot be deleted.
If multiple indexes have been established, you can arbitrarily select one of the indexes, which is used to use indexName properties.
11.2.3 Packet with index
After selecting an index, the dataset will automatically be sorted in the fields. Thus, near records are often containing the same value on the key field. For example, suppose having a table is like this:
Salesrep Customer Orderno Amount
1 1 5 100
1 1 2 50
1 2 3 200
1 2 6 75
2 1 1 10
2 3 4 200
It can be seen that the value of the Salesrep field is repeated. For the value of the Salesrep field, the value of the Customer field is also repeated. That is to say, you can packet with the salesrep field, then press the Customer field group. Obviously, the packet level here is different, and the packet established by the Salesrep field belongs to the first level, and the packet established by the Customer field belongs to the second level. In fact, the packet level depends on the order in the field in the index. The TclientDataSet can determine if the recorded value is displayed according to the packet level. For example, you may want to display data in the following form:
Salesrep Customer Orderno Amount
1 1 5 100
2 50
2 3 200
6 75
2 1 1 10
2 3 4 200
To determine what location of the current record, you can call the getGroupState function. The getGroupState function needs to pass a parameter for specifying the packet level.
11.3 calculation field
Like other data sets, you can also add calculation fields in the data set established by TclientDataSet. The value of the calculating field is calculated based on other fields in the same record.
In other data sets, as long as the user modifies the data or the current record changes, the oncalcfields event will be triggered, in other words, the value of the calculated field is calculated once.
TclientDataSet introduces the concept of "internal calculation field". Unlike the general calculation field, the value of the internal calculation field will be accessed with the value of other fields, so that only the ONCALCFIELDS event is triggered if the user modifies the data. If only the current record is changed, the oncalcfields event will not trigger the oncalcfields event. . That is, the value of the internal calculation field needs to be re-calculated.
In the handle of the oncalcfields event, first determine the state attribute. If the State property returns DSInternalcalc, the value of the internal calculation field is required at this time. If the State property returns DSCalcFields, the value of the general calculation field is required at this time.
11.4 Standard Value
TclientDataSet adds statistical features that can be based on the total sum, average, count, maximum, minimum, and minimum. These statistics will automatically follow up when users edit data.
11.4.1 Specify statistical mode
To specify how to make statistics, use the aggregates attribute. This property is a taggregates object that is used to manage a set of TaggRegate objects.
In the design period, you can open the omitted number button on the edge of the Aggregates property as shown in Figure 11.1.
Editor.
Figure 11.1 Managing a set of TaggRegate objects
Click the button to add a TaggRegate object, click the button to delete a taggregate object, click the button to move the taggregate object forward, click the button to move the taggregate object.
You can create a field for expressing a statistical value with a field editor, which must be "aggregate". Delphi 4 automatically creates a TaggRegate object and is added to the aggregates properties. Select a TaggRegate object, the Object INPector will display the properties of the object.
Where the Expression property is used to specify statistical expressions, for example:
Sum (Field1)
It can also be a more complex expression:
SUM (Qty * Price) - SUM (AmountPAID)
In the expression, you can use the following status:
.Sum calculates the sum of a set of data. .Avg calculates the average of a set of data.
.Count calculates the number of non-null values in a set of data.
.Min calculates the minimum value of a set of data.
.Max calculates the maximum value of a set of data.
In addition to the above-mentioned statistical operators, the operators that can be used in filters can be used, but they cannot nested. In an expression, there can be several statistical values or constants, but statistics and fields cannot be mixed.
SUM (Qty * Price) {legal}
Max (Field1) - Max (Field2) {legal}
AVG (discountrate) * 100 {legal}
MIN (SUM (Field1)) {illegal, not nested}
Count (Field1) - Field2 {illegal, statistical and fields cannot be mixed in an expression}
11.4.2 Specify grouping
By default, the statistical value is calculated based on all records in the data set. However, the statistical value can also be calculated for a part of the record, which requires a packet in advance.
The concept of packets has been mentioned in front of the index. You can choose which index and the largest packet level can be selected via the indexName property and the GroupingLevel property.
For example, suppose having a table is like this:
Salesrep Customer Orderno Amount
1 1 5 100
1 1 2 50
1 2 3 200
1 2 6 75
2 1 1 10
2 3 4 200
If you want to group in the Salesrep field, and specify the first level, the program code should write this:
Agg.Expression: = 'SUM (AMOUNT)';
Agg.indexname: = 'Salescust';
Agg.groupinglevel: = 1;
Agg.aggregatename: = 'Total for rep';
11.4.3 How to get a statistical value
To get a statistical value, you can call the Value function of the TaggRegate object. If the statistical value is calculated based on all records in the data set, you can call the Value function at any time. If the statistical value is based on the packet, it must be guaranteed that the current record is located within the group. Therefore, before calling value, it is best to call the getGroupState function to see if the current record is within the group.
To display a statistical value in the data control, you must create a permanent field object in advance in the field editor, which must be aggregate.
11.5 data package
Access the data from the application server from the application server via the DATA property. The program is now as follows:
Procedure TFORM1.BUTTON1CLICK (Sender: TOBJECT);
Begin
ClientDataSet1.Data: = ClientDataSet1.Provider.DataRequest (FilteredIt.Text);
END;
11.5.1 Assignment directly to the DATA property
As mentioned earlier, the client program can acquire data from the iProvider interface, or from another dataset, the latter is assigned by the DATA property. The program is now as follows:
ClientDataSet1.Data: = ClientDataSet2.data;
Once Data is assigned, you can display this data with a standard data control.
Note: When data is acquired from another data set, the log of another dataset will also be copied, but does not include the original range and filter conditions.
If you want to get data from another BDE-based data, you can use the provike of the data set component, as follows: ClientDataSet1.Data: = table1.provider.data;
If you want to get data from a custom dataset, first create a temporary TPROVIDER component, then set its DataSet property to specify this custom dataset. The program is now as follows:
TempProvider: = TDataSetProvider.create (Form1);
TempProvider.DataSet: = SOURCEDATASET;
ClientDataSet1.Data: = Tempprovider.data;
TempProvider.Free;
11.5.2 Add custom information in your packet
Customized information can be added to the packet. These custom information will also be saved to files or streams when data is stored in a file or stream. These custom information will also be copied if the packets are assigned to another data set.
To add custom information to your packet, you can call the SetOptionalParam function. To retrieve custom information from a packet, you can call GetOptionalParam. The program is now as follows:
Procedure Tapp Server.Provider1Updatedata (Sender: Tobject; DataSet: TclientDataSet);
VAR
WhenProVided: TDATETIME;
Begin
WhenProVided: = Dataset.GetoptionalParam ('TimeProvided');
...
END;
11.5.3 Cloning another data set
Calling the TclientDataSet's CloneCursor function can get the identical copy of a dataset. It is distinguished from the DATA attribute assignment.
One of the differences: Data is shared between two data sets, modify one of them will change the other.
Difference Two: In addition to data, the CloneCursor function also copies some properties and events, depending on how the reset and keepsettings parameters are set.
The CloneCursor function needs to pass three parameters, where the Source parameter specifies the source dataset, the reset parameter, and the KeepSettings parameter are used to set whether the following properties and events are replicated in addition to the data: Filter, Filtered, FilterOptions, ONFilterRecord, IndexName, Mastersource, Masterfields , Readonly, RemoteServer, ProviderName, Provider.
If the Reset and KeepSettings parameters are set to false, the above properties and events of the source dataset will be copied to the target dataset. If the reset parameter is set to True, the above properties and events of the target dataset will be emptied. If the reset parameter is set to false, the KeepSettings parameter is set to true, the above properties and events of the target dataset are unchanged, however, these attributes and events must be compatible with the cloned data.
11.6 Communication with Application Server
In the multilayer architecture, the client exchanges data with the application server via the iProvider interface. This chapter describes how to get an iProvider interface to the client, how to deliver parameters to the application server, how to write the user to the database to the database.
11.6.1 How to get an iProvider interface at the client
In a single-layer application, you don't need to use an iProvider interface in a multi-layer application that works in "Briefcase" mode. In the multilayer architecture, the client program is to exchange data with the application server, first of all, IPROVIDER interfaces must be obtained, which is used to use the RemoteServer attribute and the ProviderName property. The RemoteServer property is used to specify the MIDAS connection component of the client. The MIDAS connection component is also known as Data Broker for establishing and maintaining the connection to the application server.
After the RemoteServer property is set correctly, you can select a value for the ProviderName property in the object viewer. It is actually a TPROVIDER component on the application server.
11.6.2 Transfer parameters to the application server
The client can pass parameters to the application server, which is actually transmitted to the TQUERY component or TSTOREDPROC component on the application server. You can also set parameters during the design period.
In the design period, you can click the I omitted button on the edge of the Params property to open an editor shown in Figure 11.2.
Figure 11.2 Setting parameters
Click the button to add a parameter, click the button to delete a parameter, click the button to move a parameter, click the button to move a parameter behind.
Select a parameter, the object viewer will display the properties of the parameter (TPARAM object).
Creating a parameter can be invoked at the runtime. For example, the following code creates a parameter called Custno, and its use type is PTINPUT, the data type is ftinteger, which is set to 605.
With ClientDataSet1.Params.createParam (ftinteger, 'Custno', PTINPUT) DO
Asinteger: = 605;
After setting the parameters, if the TclientDataSet's Active property is false, as long as the Active property is set to TRUE, these parameters will be automatically passed to the application server. If the Active property is already true, call the SendParams function to pass the parameters to the application server.
Note: Parameters passed to the application server must match the parameters of the TQuery component or TSTOREDPROC component, including name, data type, and parameter type.
11.6.3 How to request data to the application server
TclientDataSet provides two properties and three methods for requesting data to the application server:
One is the fetchondemand property. If this property is set to true, TclientDataSet automatically retrieves additional packets, such as the value of the BLOB field, or the contents of the nested table as needed. If this property is set to False, the program needs to be explicitly calling getNextPacket to get these additional packets.
The second is the PacketRecords property that sets up to the maximum number of records in a packet, set to -1 to indicate all records of a data set to accommodate the data set.
The third is the GetNextPacket function, used to retrieve the next packet to the application server, and add the retrieved packet to the previously retrieved packet. This function returns the number of records actually retrieved.
The fourth is the Fetchblobs process, which is used to retrieve the value of the BLOB field from the application server. If the fetchondemand property is set to true, it is not necessary to call the fetchblobs function.
The fifth is the FetchDetails process, which is used to retrieve data in the nested table. If the Fetchondemand property is set to true, it is not necessary to call the fetchDetails function.
11.6.4 Update Database
In the multilayer architecture, users need to write the latest data to the database after the client modifies the data, which is to call the TclnessDataSet ApplyUpdates function. ApplyUpdates only needs to pass a parameter called MaxErrorS, which is used to specify an integer. When you encounter an unrecognized record exceeding this number, this update is aborted. If the MaxErrorS parameter is set to 0, it means that when you encounter an error update, the client's log remains unchanged. If the MaxErrorS parameter is set to -1, when the application server finds an error record, try updating the next record, and so all the records have been returned later.
Applyupdates automatically calls the Reconcile function, and then call the ApplyUpdates function of the TPROVIDER component on the application server to update the remote database server. No recorded by the DBMS server is returned to the client via Reconcile, and the OnReconcileError event will be triggered on the client. Finally, the Applyupdates function returns still not recognized records.
11.7 Access data in the file
To read data from a file, you can call the loadFromFile function. The LoadFromFile function needs to pass a parameter to specify the file name. The file name should contain a complete path. If the client is always read from a fixed file, you can set the filename property to specify a file name. After the TclientDataSet is turned on, it will automatically read the data from this file, and do not need to call LoadFromFile.
To read data from the stream, you can call LoadFromstream. LoadFromStream needs to pass a parameter for specifying a stream object.
Note: LoadFromFile (LoadFromstream) can only read data from a file previously saved with SaveTOFile (SaveTroupTream).
To save the data to a file, you can call the SaveTOFile function. SaveTofile needs to pass a parameter for specifying the file name. If the specified file already exists, the data in the file will be overwritten. If the client always saves the data into a fixed file, you can set the filename property to specify a file name. When the TclientDataSet is turned off, save the data to this file and does not need to call SaveTofile.
To save the data to the stream, you can call SaveTroupTream. SaveTostReam needs to pass a parameter and specify a stream object.
Note: The modifications recorded in the log remain reserved when the data is saved to the file or stream. In this way, the original data can still be restored when the loadFromFile or LoadFromStream is called next time.