在datasnap 中使用unidac 訪問數據(服務器端)


 

從delphi 6 開始,datasnap 作為delphi 自帶的多層框架,一直更新到最新的delphi 10.3 。同時逐步增加了很多新的功能

,比如支持REST 調用,支持 IIS ,apache 等服務器。今天簡單介紹一下如何在datasnap 中使用unidac 訪問數據庫。

首先,按照向導生成一個標准的datasnap 服務器。

 

點完成就自動生成對應的工程文件

 

 

 

其中

  • DSServer — 用來控制數據c傳輸和服務類;
  • DSServerClass — 用來定義可供客戶端調用的服務器類方法;
  • DSHTTPService — 用來使用HTTP 協議訪問服務器;
  • DSAuthenticationManager —控制調用服務器方法的用戶認證及授權;
  • DSTCPServerTransport — 用來使用TCP/IP訪問服務器。

我們可以通過代碼做一些對應的設置

主界面代碼:

procedure Tmainf.btStartClick(Sender: TObject);
begin
 if not ServerContainer1.DSServer1.Started then
  begin
    ServerContainer1.DSTCPServerTransport1.Port := StrToInt(edTCPIPPort.Text);
    ServerContainer1.DSHTTPService1.DSPort      := StrToInt(edHTTPPort.Text);
    ServerContainer1.DSServer1.Start;
    mStatus.Lines.Add( Formatdatetime('yyyy-mm-dd hh:nn:ss',now) + 'TCP/IP 啟動偵聽');
    ServerContainer1.DSHTTPService1.Start;
    mStatus.Lines.Add(Formatdatetime('yyyy-mm-dd hh:nn:ss',now) +'HTTP 啟動偵聽');
    btStart.Caption := '停止';
  end
  else
  begin
    ServerContainer1.DSHTTPService1.Stop;
    mStatus.Lines.Add(Formatdatetime('yyyy-mm-dd hh:nn:ss',now) + 'TCP/IP 停止偵聽');
    ServerContainer1.DSServer1.Stop;
    mStatus.Lines.Add(Formatdatetime('yyyy-mm-dd hh:nn:ss',now) +'HTTP 停止偵聽');
    btStart.Caption := '啟動';
  end;
end;
procedure TServerContainer1.DSServer1Connect(
  DSConnectEventObject: TDSConnectEventObject);
var
  ci: TDBXClientInfo;
begin
  ci := DSConnectEventObject.ChannelInfo.ClientInfo;
  mainf.mStatus.Lines.Add(Format('客戶端以 %s 方式連接 IP: %s, 端口: %s', [ci.Protocol, ci.IpAddress, ci.ClientPort]));

end;

procedure TServerContainer1.DSServer1Disconnect(
  DSConnectEventObject: TDSConnectEventObject);

var
  ci: TDBXClientInfo;
begin
  ci := DSConnectEventObject.ChannelInfo.ClientInfo;
  mainf.mStatus.Lines.Add(Format('客戶端以 %s 方式斷開 IP: %s, Port: %s', [ci.Protocol, ci.IpAddress, ci.ClientPort]));
end;

以上datasnap 服務器端基本上就設置好了,現在我們要增加數據庫訪問功能。數據庫訪問控件毫無疑問,使用unidac.

本次還是以postgresql 為例。

啟動postgresql 服務器

(這個服務器在哪里下載?請猛戳 www.haosql.com).

 運行數據庫腳本

CREATE TABLE dept
(
  deptno serial NOT NULL,
  dname character varying(14),
  loc character varying(13),
  cnt integer,
  CONSTRAINT "PK_MASTER" PRIMARY KEY (deptno)
);
 
CREATE TABLE emp
(
  empno serial NOT NULL,
  ename character varying(10),
  job character varying(9),
  mgr integer,
  hiredate timestamp without time zone,
  sal real,
  comm real,
  deptno integer NOT NULL,
  CONSTRAINT "PK_DETAIL" PRIMARY KEY (deptno, empno)
);
 
CREATE TABLE users
(
  id numeric NOT NULL,
  username character(20) NOT NULL,
  passwd character(20) NOT NULL,
  CONSTRAINT pk_users_id PRIMARY KEY (id),
  CONSTRAINT uq_users_name UNIQUE (username)
);
 
CREATE OR REPLACE FUNCTION sp_check_user(a_username character DEFAULT ''::bpchar, a_passwd character DEFAULT ''::bpchar)
  RETURNS boolean AS
$BODY$BEGIN
IF EXISTS (SELECT 1 FROM users WHERE username = a_username AND passwd = a_passwd) THEN
RETURN True;
ELSE
RETURN False;
END IF;
END;
$BODY$
  LANGUAGE plpgsql;
 
CREATE OR REPLACE FUNCTION sp_dept_modify(a_deptno numeric DEFAULT (-1), a_dname character DEFAULT ''::bpchar, a_loc character DEFAULT ''::bpchar, a_op_type numeric DEFAULT 0)
  RETURNS void AS
$BODY$begin
  case a_op_type
    when 0 then delete from dept where deptno = a_deptno;
    when 1 then insert into dept (deptno, dname, loc) values (a_deptno, a_dname, a_loc);
    else update dept set dname = a_dname, loc = a_loc where deptno = a_deptno;
  end case;
end;$BODY$
  LANGUAGE plpgsql;
 
CREATE OR REPLACE FUNCTION sp_emp_modify(a_empno numeric DEFAULT (-1), a_ename character DEFAULT ''::bpchar, a_job character DEFAULT ''::bpchar, a_mgr numeric DEFAULT 0, a_hiredate timestamp without time zone DEFAULT (now())::timestamp without time zone, a_sal numeric DEFAULT 0, a_comm numeric DEFAULT 0, a_deptno numeric DEFAULT (-1), a_op_type numeric DEFAULT 0)
  RETURNS void AS
$BODY$begin
  case a_op_type
    when 0 then delete from emp where empno = a_empno;
    when 1 then insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (a_empno, a_ename, a_job, a_mgr, a_hiredate, a_sal, a_comm, a_deptno);
    else update emp set ename = a_ename, job = a_job, mgr = a_mgr, hiredate = a_hiredate, sal = a_sal, comm = a_comm where empno = a_empno;
  end case;
end;$BODY$
  LANGUAGE plpgsql;

 

 

在ServerMethodsUnit1 里面放置對應的控件。

設置數據庫連接

 

 設置對應的sql 參數

添加對應的 服務器端代碼

 function GetDept: TDataSet;
    function GetEmp(DeptNo: integer = -1): TDataSet;
    function CheckUser(username: string = ''; passwd: string = ''):boolean;
    procedure DeptModify(DeptNo: integer = -1; DName: string = ''; Loc: string = ''; op_type: integer = 0);
    procedure EmpModify(Empno: integer = -1;
                        EName: string = '';
                        Job: string = '';
                        Mgr: integer = 0;
                        HireDate: TDateTime = 0;
                        Sal: double = 0;
                        Comm: double = 0;
                        Deptno:integer = -1;
                        op_type: integer = 0);

如圖

 

 

procedure TServerMethods1.DeptModify(DeptNo: integer; DName, Loc: string;
  op_type: integer);
begin
     usp_dept_modify.ParamByName('a_deptno').AsInteger := DeptNo;
  usp_dept_modify.ParamByName('a_dname').AsString := DName;
  usp_dept_modify.ParamByName('a_loc').AsString := Loc;
  usp_dept_modify.ParamByName('a_op_type').AsInteger := op_type;
  usp_dept_modify.Execute;
end;


procedure TServerMethods1.EmpModify(Empno: integer; EName, Job: string;
  Mgr: integer; HireDate: TDateTime; Sal, Comm: double; Deptno,
  op_type: integer);
begin
      usp_emp_modify.ParamByName('a_empno').AsInteger := Empno;
  usp_emp_modify.ParamByName('a_ename').AsString := EName;
  usp_emp_modify.ParamByName('a_job').AsString := Job;
  usp_emp_modify.ParamByName('a_mgr').AsInteger := Mgr;
  usp_emp_modify.ParamByName('a_hiredate').AsDateTime := HireDate;
  usp_emp_modify.ParamByName('a_sal').AsFloat := Sal;
  usp_emp_modify.ParamByName('a_Comm').AsFloat := Comm;
  usp_emp_modify.ParamByName('a_deptno').AsInteger := Deptno;
  usp_emp_modify.ParamByName('a_op_type').AsInteger := op_type;
  usp_emp_modify.Execute;
end;

function TServerMethods1.GetDept: TDataSet;
begin
    uqDept.Close;
  uqDept.Open;
  Result := uqDept;
end;

function TServerMethods1.GetEmp(DeptNo: integer): TDataSet;
begin
     uqEmp.Close;
  uqEmp.ParamByName('DEPTNO').AsInteger := DeptNo;
  uqEmp.Open;
  Result := uqEmp;
end;


function TServerMethods1.EchoString(Value: string): string;
begin
  Result := Value;
end;
function TServerMethods1.ReverseString(Value: string): string;
begin
  Result := System.StrUtils.ReverseString(Value);
end;

 

 服務器端就OK 了。

運行起來。

 在瀏覽器里面我們也可以直接訪問它的REST 服務

 

 

 

 

 

 剩下就是客戶端的編寫了,我們放到下一篇。

先來個客戶端效果照。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM