Synopse mORMot框架样例学习03 - NamedPipe Client-Server

前边的例01和例02分别展示了静态服务器及嵌入式SQLite3服务器的实现方法,例03是命名管道客户端-服务器,例01中用JSON文件存储数据(按我的理解,每一个SQLRecord就是一个表格,在存储的时候多个表格应该需要多个JSON文件取存储),例02中使用SQLite3数据库存储,只需要一个.db3数据库文件就能存放所有的SQLRecord(表格),例03中实现了客户端-服务器的通讯,客户端的数据需要传递到服务器去处理.

先看看服务器是怎么运行的,例03主单元Unit2.pas实现了命名管道服务器,在代码中看比较方便,省略了部分代码,只看主要的部分:

unit Unit2;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,
  // 下方是mORMot单元
  SynCommons, mORMot, mORMotSQLite3, SynSQLite3Static, StdCtrls, SampleData;
type
  TForm1 = class(TForm)
   { ...(省略) }
  public
    Model: TSQLModel; { 声明SQL操作模型 }
    Server: TSQLRestServerDB; { 服务器的声明 }
  end;
{ ...(省略) }
implementation
{$R *.dfm}
{ ...(省略) }
procedure TForm1.FormCreate(Sender: TObject);
begin
  Model := CreateSampleModel; { 窗口创建的时候初始化数据库操作模型 }
  Server := TSQLRestServerDB.Create(Model, ChangeFileExt(ExeVersion.ProgramFileName, '.db3')); { 初始化一个Rest服务器,这里和样例2是一样的 }
  Server.CreateMissingTables; { 根据模型Model创建必须的表格(也就是SampleData单元定义的类) }
  Server.ExportServerNamedPipe('03'); { 创建命名管道,名字为03,客户端初始化的时候必须和此名称一致才能进行进程间通讯 }
end;
{ ...(省略) }
end.

 

然后是客户端部分,这一次我想把SampleData单元进行简单的改造下,添加一个用户信息类,用于存储用户名和密码,这样我们在初始化数据库的时候会有2个表格SampleRecord和UserInfo,还是看代码的注释进行说明:

unit SampleData;
interface
uses
  SynCommons, mORMot;
type
  TSQLSampleRecord = class(TSQLRecord)
  { ...省略 }
  end;
 
  { 我们再添加一个类,用于记录用户名和密码 }
  TSQLUserInfo = class(TSQLRecord)
  private
    fUserName: RawUTF8;
    fPassWord: RawUTF8;
    fRemark: TSQLSampleRecord;
  published
    property UserName: RawUTF8 read fUserName write fUserName;
    property PassWord: RawUTF8 read fPassWord write fPassWord;
    property Remark: TSQLSampleRecord read fRemark write fRemark;
  end;
 
function CreateSampleModel: TSQLModel;
 
implementation
 
function CreateSampleModel: TSQLModel;
begin
  result := TSQLModel.Create([TSQLSampleRecord, TSQLUserInfo{ 创建模型的时候要加上我们新定义的类 }]);
end;
 
end.

 

客户端同样需要进行一些改造,我们需要输入用户名和密码信息,然后一同添加到数据库中,改造后是这个样子的:

在这里,客户端的工程单元必须创建客户端命名管道,并且管道的名字要与服务端保持一致:

{ 创建与服务端一致的客户端命名管道,以便与服务端通信 }  
Form1.Database := TSQLRestClientURINamedPipe.Create(Form1.Model, '03');

 

主单元Unit1.pas实现代码如下:

unit Unit1;
interface
uses
  {$ifdef MSWINDOWS}
  Windows, Messages, Graphics,
  {$endif}
  Classes, SysUtils, Forms, Controls, Dialogs, StdCtrls, SynCommons, SynTable,
  mORMot, SampleData;
type
{ ...省略 }
 
implementation
 
{$ifdef FPC}
{$R *.lfm}
{$else}
{$R *.dfm}
{$endif}
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  Model := CreateSampleModel;  { 调用后SampleRecord和UserInfo同时对数据库中对应的2个表进行映射 }
end;
 
procedure TForm1.AddButtonClick(Sender: TObject);
var
  Rec: TSQLSampleRecord;
  UserRec: TSQLUserInfo; { 声明用户信息类 }
begin
  Rec := TSQLSampleRecord.Create;
  UserRec := TSQLUserInfo.Create; { 创建实例 }
  try
    Rec.Name := StringToUTF8(NameEdit.Text);
    Rec.Question := StringToUTF8(QuestionMemo.Text);
    Rec.Log := StringToUTF8('added ' + NameEdit.Text + ' ' + QuestionMemo.Text);
    if Database.Add(Rec, true) = 0 then
      ShowMessage('Error adding the data')
    else
    begin
      MemoLog.Lines.Add('Name: ' + NameEdit.Text + ';' + 'Question: ' + QuestionMemo.Text + ';');
      NameEdit.Text := '';
      QuestionMemo.Text := '';
      NameEdit.SetFocus;
    end;
    { 把用户名和密码写进数据库 }
    UserRec.UserName := StringToUTF8(UserNameEdit.Text);
    UserRec.PassWord := StringToUTF8(PassWordEdit.Text);
    if DataBase.Add(UserRec, true) = 0 then
      ShowMessage('Error adding the data')
    else
    begin
      UserNameEdit.Clear;
      PassWordEdit.Clear;
    end;
  finally
    Rec.Free;
    UserRec.Free;
  end;
end;
{ ...省略 }
end.

 

需要先启动服务端,然后再启动客户端,同样写入3组记录,然后用sqliteadmin看看数据库的情况:

数据库存储情况如下:

可以看到,和预想的情况一样,例02和例03不管是在嵌入式数据库还是客户端-服务器的设计,除了DataBase初始化的部分有少许不同,其他代码可以原封不动,感觉很是方便.到这里基本上摸清了例01-例03样例的目的,就是最基础的ORM操作,和不同数据存储的方式使用,对照文档看一下,确实如文档所说,作者并没有夸大框架的功能,但是总感觉不太习惯作者的英语表达方式,不动手实践,有的东西光看文档的确能让人感到迷糊,继续努力学习.

 

 
posted @ 2020-11-27 11:17  dqi1999  阅读(143)  评论(0)    收藏  举报