This is the sequel to this topic, not read the first part of the look here:
http://bbs.2ccc.com/topic.asp?topicid=548153
The reason for the second part is because the first part of the keep abreast too much, read inconvenient, wasting everyone's time.
Today we talk about the theme is: Delphi's Datasnap substantive analysis
First of all, the Datasnap Chinese should be translated into what, my personal translation method is: Data snapshot.
We do not get dizzy by so much information about DATASNAP, in fact, the principle is very simple.
To make Datasnap understand, must first the client's TClientDataSet control to understand, will not, find degrees Niang. Hereinafter referred to as CDs.
CDS has two olevarient attributes, one called data, and one called Delta. The multi-layered framework of Delphi depends on the two brothers. Data is used by the client to retrieve the information from the server side, and the delta is used by the client to save the modified data to the server.
So, this is simple, the server side as long as the output data can be achieved, receive delta, three-tier application is up. Who does the server-side work for? Tdatasetprovider, hereinafter referred to as DP.
The DP has a data property, a olevariant type, and a Applyupdate method that accepts the delta as an input parameter.
Having understood this, we can completely abandon Delphi's complex datasnap and build a simple, reliable and efficient multi-layered framework.
Server-side natural with Mormot manuscripts, with THTTPAPISERVER+DP, give full play to the power of HTTP. Sys, standing on the shoulders of giants, the powerful.
Client we use Delphi10.2.3 to do, support Pc/android/ios, with Cds+tnethttprequest to do.
Do not consider the mobile phone, continue to use Delphi7 to do PC application of iron powder, with Cds+thttpclientsocket (Mormot).
Data and Delta are both variants and cannot be transmitted over the network, we need these two to become strings, first two functions:
{$IFNDEF UNICODE}
Type
rawbytestring = ansistring;
{$ENDIF}
function variantarraytostring (const v:olevariant): rawbytestring;
Var
P:pointer;
Size:integer;
Begin
Result: = ';
If Varisarray (v) and (VarType (v) and vartypemask = Varbyte) THEN BEGIN
Size: = Vararrayhighbound (V, 1)-Vararraylowbound (V, 1) + 1;
If Size > 0 THEN BEGIN
SetLength (Result, Size);
P: = Vararraylock (V);
Try
Move (p^, result[1], Size);
Finally
Vararrayunlock (V);
End
End
End
End
function Stringtovariantarray (const s:rawbytestring): olevariant;
Var
P:pointer;
Begin
Result: = NULL;
If Length (S) > 0 THEN BEGIN
Result: = Vararraycreate ([0, Length (S)-1], varbyte);
P: = Vararraylock (Result);
Try
Move (S[1], p^, Length (S));
Finally
Vararrayunlock (Result);
End
End
End
Did you see that? Both the data and the delta are stored in a byte stream. There are two ways to transfer to a byte stream, one is to stream, contenttype to Application/octet-stream, and the other to encode the byte stream base64 as plain text. Big data streams can be added to the compression/decompression mechanism, and confidential data can be added to the encryption/decryption mechanism.
Base64 encoding and decoding, Delphi comes with, unit name is ENCDDECD. There are two functions of encodestring and decodestring.
In order to get everyone to understand the principle, we first put aside the network transport layer, the CDs and DP in a room to make them together.
Unit Dp2cdsmain;
Interface
Uses
Forms, Dbclient, DB, Provider, ADODB, Controls, Grids, Dbgrids, Comctrls,
Classes, Stdctrls;
Type
TForm2 = Class (Tform)
Serverdata:tadodataset;
Button1:tbutton;
Clientdata:tclientdataset;
Serverdatasetprovider:tdatasetprovider;
Pagecontrol1:tpagecontrol;
Tabsheet2:ttabsheet;
Datasource1:tdatasource;
Dbgrid1:tdbgrid;
Procedure Button1Click (Sender:tobject);
Private
{Private declarations}
Public
{Public declarations}
End
Var
Form2:tform2;
Implementation
Uses sysutils, variants, ENCDDECD;
{$R *.DFM}
{$IFNDEF UNICODE}
Type
rawbytestring = ansistring;
{$ENDIF}
function variantarraytostring (const v:olevariant): rawbytestring;
Var
P:pointer;
Size:integer;
Begin
Result: = ';
If Varisarray (v) and (VarType (v) and vartypemask = Varbyte) THEN BEGIN
Size: = Vararrayhighbound (V, 1)-Vararraylowbound (V, 1) + 1;
If Size > 0 THEN BEGIN
SetLength (Result, Size);
P: = Vararraylock (V);
Try
Move (p^, result[1], Size);
Finally
Vararrayunlock (V);
End
End
End
End
function Stringtovariantarray (const s:rawbytestring): olevariant;
Var
P:pointer;
Begin
Result: = NULL;
If Length (S) > 0 THEN BEGIN
Result: = Vararraycreate ([0, Length (S)-1], varbyte);
P: = Vararraylock (Result);
Try
Move (S[1], p^, Length (S));
Finally
Vararrayunlock (Result);
End
End
End
Procedure Tform2.button1click (Sender:tobject);
Var
Vdatain, Vdataout:olevariant;
Cdatain, cdataout:rawbytestring;
Begin
Clientdata.close;
Vdatain: = Serverdatasetprovider.data;
Cdatain: = variantarraytostring (Vdatain);
Analog Network Transfer
Cdataout:=cdatain;
Vdataout: = Stringtovariantarray (cdataout);
Clientdata.data: = Vdataout;
End
End.
I have reproduced here an article to elaborate on the use of CDs:
Https://www.cnblogs.com/c5soft/p/9121775.html
Did not carefully read the mobile phone version of the CDs, do not know is not fully realized the function of the PC version, used by many friends post.
Say humorous, the CDs right-click menu has a "Assign Local data ..." That can copy any Tdataset data on the same form into CDs, how do you do that? I guess that's the use of DP, it should be written like this:
var Dp:tdatasetprovider;
Begin
Dp:=tdatasetprovider.create;
Dp. Dataset=adodataset1;
CLIENTDATASET1.DATA:=DP. Data;
Dp. Free
End
Use HTTP. sys to let Delphi's multi-tier services really fly up "part two"