Delphi to do three layer development, many people will put a tclientdataset on the client, the middle-tier remote data module corresponding to put a tdatasetprovider, and then connected. In fact, this method is very cumbersome, and the procedure carbuncle swollen unwilling, Not good maintenance. We all know that TClientDataSet's Delta property records all modifications to the data, and it allows us to easily implement a common approach to single-table updates.
First, add a method to the middle tier, called Applyupdates. The method is defined as follows:
function applyupdates (const updatetable:string;delta:variant;out err:string): Boolean;
The parameter updatetable refers to the name of the table to be updated, and Delta refers to the Delta property of the TClientDataSet passed over, and if the update error err returns the wrong content. This method is implemented below, first put a query on Datamodule, Query connect to connection, and then put a tdatasetprovider even query. The code is as follows:
function trodm.applyupdates (const updatetable:string;delta:variant;out err:string): Boolean;
Const sql= ' select * from%s where 1<>1 ';
var sqlstr:string;
Errcount:integer;
Begin
Result:=false;
Sqlstr:=format (sql,[updatetable]);
Try
Conn.begintrans;
Query.close;
QUERY.SQL.TEXT:=SQLSTR;
Query.open;
Provider.applyupdates (Delta,-1,errcount);
result:=errcount=0;
If Result Then
Conn.committrans
else Conn.rollbacktrans;
Except
On E:exception do
Begin
Conn.rollbacktrans;
Err:=e.message;
End
End
End
In this case, the general Update method has been completed. However, the client's clientdataset is not yet able to query the display data, so write a query method:
function Querysql (const sqlstr:string;out data:variant;out err:string): Boolean;
Parameter SQLSTR is the query statement to hold the row, data returns the query result, error when err returns error message
The Querysql implementation code is as follows:
function Trodm.querysql (const sqlstr:string;out data:variant;out err:string): Boolean;
Begin
Result:=false;
Try
Query.close;
QUERY.SQL.TEXT:=SQLSTR;
Query.sql.Open;
Data:=provider.data;
Result:=true;
Except
On E:exception do
Err:=e.message;
End
End
Here, the middle layer code is finished, the client's call is simple. For example, the client has a data module DM, put a dcomconnection or socketconnection, named Conn. For example, we are now going to do a product management function, Put a tclientdataset on the form called CDs, put Datasource,dbgrid, etc., set the corresponding properties. Then query back all data when the form was created (create event), with the following code:
Const sql= ' select * from XXXX ';
var data:variant;
err:string;
Begin
If Dm.Conn.AppServer.QuerySQL (Sql,data,err) Then
Cds.data:=data
Else MessageBox (Self.handle,pchar (' Query data error: ' +err '), ' error ', mb_ok+mb_iconerror);
End
Then there are "add", "Modify", "delete" button, the code is the same as we normally do, such as "add" the Code of the button:
Cds.append;
Cds.fieldbyname (' xxx '). asinteger:=xxx;
//....
Cds.post;
Modifications, Delete also writes like this. But now there's a small problem with this table's primary key generation problem, where we can't use the self-increment primary key to generate the primary key ourselves, so you have to write a middle layer in the middle layer to generate the primary key method, the "Increase" button to generate the primary key, and then the above operation. No more talking here .
Additions and deletions after the data is still in the client's memory, want to save to the remote middle-tier server to use the method we just had, the following is the "Save" button under the code:
var err:string;
Begin
If CDs. Changecount=0 then exit;//data is not changed, you don't have to commit.
If Dm.Conn.AppServer.ApplyUpdates (' xxx ', CDs. Delta,err) Then//xxx is the name of the table.
Begin
MessageBox (Self.handle, ' Save succeeded! ', ' hint ', mb_ok+mb_iconinformation);
Cds. mergechangelog;//merging all the changed data
End Else MessageBox (Self.handle,pchar (' Save error: ' +err), ' Error ', mb_ok+mb_iconerror);
End
This article is also finished. With this method, the basic data update of those single tables can also be written as an ancestor class, as long as a virtual method with the name of the update table is added, such as: function tablename:string;virtual; Then its descendants just override this method, return their own table name, the other code is not written.
Delphi Three Layer Development tips: TClientDataSet's delta Magical