source upload
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
TSynRestDataset
|
||||
===============
|
||||
|
||||
By *EMartin* (Esteban Martin).
|
||||
|
||||
|
||||
# Presentation
|
||||
|
||||
Migrating from *RemObjects* to *mORMot* I had to implement a GUI functionality that *RemObjects* has, an editable dataset connected through URL (RO version 3 use SOAP and other components adapters, etc.).
|
||||
|
||||
My implementation is basic and the most probably is not the best, but works for me, the same use RESTful URL for get and update data, also get data from a *mORMot* interface based services returning a *mORMot* JSON array but cannot update because the table not exists.
|
||||
|
||||
In this folder there are two units: `SynRestVCL.pas` and `SynRestMidasVCL.pas`, both have some duplicated code from its counterpart (`SynDBVCL.pas` and `SynDBMidasVCL.pas`) and the others, but the rest are modifications with use of RESTful instead of the `TSQLDBConnection` (this require the database client installed in the client machine).
|
||||
|
||||
A `TSQLModel` is required because the `TSynRestDataset` get the fields definition column type and size from this. Also is used from the `TSQLRecord` the defined validations (I used `InternalDefineModel`) and the `ComputeFieldsBeforeWrite` (I used this for default values).
|
||||
|
||||
This was developed with Delphi 7 on Windows 7 and probably (almost sure) is not cross platform.
|
||||
|
||||
If this serves for others may be the best option will be that *ab* integrate this in the framework and make this code more *mORMot*. Meanwhile I will update on the google drive.
|
||||
I hope this is helpful to someone.
|
||||
|
||||
# Example 1: from a table
|
||||
|
||||
// defining the table
|
||||
TSQLRecordTest = class(TSQLRecord)
|
||||
private
|
||||
fDecimal: Double;
|
||||
fNumber: Double;
|
||||
fTestID: Integer;
|
||||
fText: RawUTF8;
|
||||
fDateTime: TDateTime;
|
||||
protected
|
||||
class procedure InternalDefineModel(Props: TSQLRecordProperties); override;
|
||||
public
|
||||
procedure ComputeFieldsBeforeWrite(aRest: TSQLRest; aOccasion: TSQLEvent); override;
|
||||
published
|
||||
property Test_ID: Integer read fTestID write fTestID;
|
||||
property Text: RawUTF8 index 255 read fText write fText;
|
||||
property Date_Time: TDateTime read fDateTime write fDateTime;
|
||||
property Number: Double read fNumber write fNumber;
|
||||
property Decimal_: Double read fDecimal write fDecimal;
|
||||
end;
|
||||
|
||||
...
|
||||
|
||||
{ TSQLRecordTest }
|
||||
|
||||
procedure TSQLRecordTest.ComputeFieldsBeforeWrite(aRest: TSQLRest; aOccasion: TSQLEvent);
|
||||
begin
|
||||
inherited;
|
||||
fDateTime := Now;
|
||||
end;
|
||||
|
||||
class procedure TSQLRecordTest.InternalDefineModel(Props: TSQLRecordProperties);
|
||||
begin
|
||||
AddFilterNotVoidText(['Text']);
|
||||
AddFilterOrValidate('Text', TSynValidateNonNull.Create);
|
||||
end;
|
||||
|
||||
// client
|
||||
type
|
||||
TForm3 = class(TForm)
|
||||
DBGrid1: TDBGrid;
|
||||
DBNavigator1: TDBNavigator;
|
||||
btnOpen: TButton;
|
||||
edtURL: TEdit;
|
||||
dsRest: TDataSource;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure btnOpenClick(Sender: TObject);
|
||||
procedure DBNavigator1Click(Sender: TObject; Button: TNavigateBtn);
|
||||
private
|
||||
{ Private declarations }
|
||||
fRestDS: TSynRestDataset;
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
|
||||
...
|
||||
|
||||
procedure TForm3.FormCreate(Sender: TObject);
|
||||
begin
|
||||
fRestDS := TSynRestDataset.Create(Self);
|
||||
fRestDS.Dataset.SQLModel := TSQLModel.Create([TSQLRecordTest], 'root');
|
||||
dsRest.Dataset := fRestDS;
|
||||
end;
|
||||
|
||||
procedure TForm3.btnOpenClick(Sender: TObject);
|
||||
begin
|
||||
fRestDS.Close;
|
||||
fRestDS.CommandText := edtURL.Text; // edtURL.Text = 'http://localhost:8888/root/Test/select=*
|
||||
fRestDS.Open;
|
||||
// you can filter by
|
||||
// where: fRestDS.CommandText := edtURL.Text; // edtURL.Text = 'http://localhost:8888/root/Test/select=*&where=CONDITION
|
||||
// fRestDS.Open;
|
||||
// named parameter: fRestDS.CommandText := edtURL.Text; // edtURL.Text = 'http://localhost:8888/root/Test/select=*&where=:PARAMNAME
|
||||
// fRestDS.Params.ParamByName('PARAMNAME').Value := XXX
|
||||
// fRestDS.Open;
|
||||
end;
|
||||
|
||||
procedure TForm3.DBNavigator1Click(Sender: TObject; Button: TNavigateBtn);
|
||||
begin
|
||||
if (Button = nbPost) then
|
||||
fRestDS.ApplyUpdates(0);
|
||||
end;
|
||||
|
||||
# Example 2: from a service
|
||||
|
||||
// defining the table, the service name and operation name are required
|
||||
TSQLRecordServiceName_OperationName = class(TSQLRecord)
|
||||
private
|
||||
fText: RawUTF8;
|
||||
published
|
||||
property Text: RawUTF8 index 255 read fText write fText;
|
||||
end;
|
||||
|
||||
...
|
||||
|
||||
// server (the implementation)
|
||||
|
||||
TServiceName =class(TInterfacedObjectWithCustomCreate, IServiceName)
|
||||
public
|
||||
...
|
||||
// this function can also be function OperationName(const aParamName: RawUTF8): RawUTF8;
|
||||
function OperationName(const aParamName: RawUTF8; out aData: RawUTF8): Integer;
|
||||
...
|
||||
end;
|
||||
|
||||
...
|
||||
|
||||
function TServiceName.OperationName(const aParamName: RawUTF8; out aData: RawUTF8): Integer;
|
||||
begin
|
||||
Result := OK;
|
||||
aData := '[{"text":"test"},{"text":"test1"}]';
|
||||
end;
|
||||
|
||||
...
|
||||
|
||||
// client
|
||||
type
|
||||
TForm3 = class(TForm)
|
||||
DBGrid1: TDBGrid;
|
||||
DBNavigator1: TDBNavigator;
|
||||
btnOpen: TButton;
|
||||
edtURL: TEdit;
|
||||
dsRest: TDataSource;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure btnOpenClick(Sender: TObject);
|
||||
procedure DBNavigator1Click(Sender: TObject; Button: TNavigateBtn);
|
||||
private
|
||||
{ Private declarations }
|
||||
fRestDS: TSynRestDataset;
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
|
||||
...
|
||||
|
||||
procedure TForm3.FormCreate(Sender: TObject);
|
||||
begin
|
||||
fRestDS := TSynRestDataset.Create(Self);
|
||||
fRestDS.Dataset.SQLModel := TSQLModel.Create([TSQLRecordServiceName_OperationName], 'root');
|
||||
dsRest.Dataset := fRestDS;
|
||||
end;
|
||||
|
||||
procedure TForm3.btnOpenClick(Sender: TObject);
|
||||
begin
|
||||
fRestDS.Close;
|
||||
fRestDS.CommandText := edtURL.Text; // edtURL.Text = 'http://localhost:8888/root/ServiceName.OperationName?aParamName=XXX
|
||||
fRestDS.Open;
|
||||
// you can filter by named parameter:
|
||||
// fRestDS.CommandText := edtURL.Text; // 'http://localhost:8888/root/ServiceName.OperationName?aParamName=:aParamName
|
||||
// fRestDS.Params.ParamByName('aParamName').Value := XXX
|
||||
// fRestDS.Open;
|
||||
end;
|
||||
|
||||
procedure TForm3.DBNavigator1Click(Sender: TObject; Button: TNavigateBtn);
|
||||
begin
|
||||
if (Button = nbPost) then
|
||||
fRestDS.ApplyUpdates(0); // raise an error "Cannot update data from a service"
|
||||
end;
|
||||
|
||||
|
||||
# Forum Thread
|
||||
|
||||
See http://synopse.info/forum/viewtopic.php?id=2712
|
||||
|
||||
# License
|
||||
|
||||
Feel free to use and/or append to Lib and extend if needed.
|
Reference in New Issue
Block a user