从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 = -): TDataSet;
function CheckUser(username: string = ''; passwd: string = ''):boolean;
procedure DeptModify(DeptNo: integer = -; DName: string = ''; Loc: string = ''; op_type: integer = );
procedure EmpModify(Empno: integer = -;
EName: string = '';
Job: string = '';
Mgr: integer = ;
HireDate: TDateTime = ;
Sal: double = ;
Comm: double = ;
Deptno:integer = -;
op_type: integer = );

如图

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 服务

剩下就是客户端的编写了,我们放到下一篇。

先来个客户端效果照。

在datasnap 中使用unidac 访问数据(服务器端)的更多相关文章

  1. 在datasnap 中使用unidac 访问数据(客户端)

    前面我们讲了如何使用unidac 在datasnap 的服务端访问数据库,今天大概讲一下客户端如何访问 前面做的服务器?其实这个客户端适合任何datasnap 服务端. 首先我们建一个应用,并加入一个 ...

  2. .NET Core2.0 MVC中使用EF访问数据

    使用环境:Win7+VS2017 一.新建一个.NET Core2.0的MVC项目 二.使用Nuget添加EF的依赖 输入命令:Install-Package Microsoft.EntityFram ...

  3. unidac 访问sql server 字符查询参数失效问题及解决办法

    在帮朋友调试kbmmw 服务器的时候,发现用uindac 访问sql server作为后台时,碰见一个问题. 具体如下: cx.Close; cx.sql.add('select * from T w ...

  4. 在 SharePoint 2010 中访问数据

    转:http://blog.banysky.net/?p=81001 数据访问的关键方法有哪些? | 使用查询类 | 使用 SPQuery | 使用 SPSiteDataQuery | 使用 LINQ ...

  5. 【转】在Spring中基于JDBC进行数据访问时怎么控制超时

    http://www.myexception.cn/database/1651797.html 在Spring中基于JDBC进行数据访问时如何控制超时 超时分类 超时根据作用域可做如下层级划分: Tr ...

  6. 【C#】访问泛型中的List列表数据

    光看标题的确不好说明问题,下面描述一下问题场景: 已知后端自定义的返回的Json数据结构如下: response: { "message": "返回成功", & ...

  7. Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅

    在上一篇Spring中使用JdbcTemplate访问数据库中介绍了一种基本的数据访问方式,结合构建RESTful API和使用Thymeleaf模板引擎渲染Web视图的内容就已经可以完成App服务端 ...

  8. vue中访问数据接口的配置

    业务API接口地址: http://localhost:3816/api/ 前端UI浏览地址:http://127.0.0.1:8080/#/home 由于同源策略的问题: 需要配置代理: 在开发环境 ...

  9. PyQt(Python+Qt)学习随笔:树型部件的QTreeWidgetItem项中列不同角色数据的有关访问方法

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 树型部件QTreeWidget中的QTreeWidgetItem项中可以有多列数据,每列数据可以根据 ...

随机推荐

  1. python读取指定字节长度的文本

    软件版本 Python 2.7.13;   Win 10 场景描述 1.使用python读取指定长度的文本: 2.使用python读取某一范围内的文本. Python代码 test.txt文本内包含的 ...

  2. 廖雪峰Java6 IO编程-2input和output-6classpath资源

    1.从classpath读取文件可以避免不同环境下文件路径不一致的问题. Windows和Linux关于路径的表示不一致 Windows:C:\conf\default.properties Linu ...

  3. 两个有序数组中的中位数以及求第k个最小数的值

    解法参考 <[分步详解]两个有序数组中的中位数和Top K问题> https://blog.csdn.net/hk2291976/article/details/51107778 里面求中 ...

  4. Python全栈开发记录_第一篇(循环练习及杂碎的知识点)

    Python全栈开发记录只为记录全栈开发学习过程中一些难和重要的知识点,还有问题及课后题目,以供自己和他人共同查看.(该篇代码行数大约:300行) 知识点1:优先级:not>and 短路原则:a ...

  5. java.io.UnsupportedEncodingException

    启动项目抛错: java.io.UnsupportedEncodingException: 1 at java.lang.StringCoding.decode(StringCoding.java:1 ...

  6. HTTP协议规定,客户端的编写

    HTTP协议是网络应用层协议,建立在TCP/IP协议基础上.HTTP协议基于客户/服务器模式,客户端主动发出HTTP请求,服务器接收HTTP请求,返回HTTP响应结果.HTTP协议对HTTP请求,以及 ...

  7. 第三篇、Python函数

    1.函数和过程的定义: 1) 函数定义:函数是逻辑结构化和过程化的一种编程方法. 2) 过程定义:过程就是简单特殊没有返回值的函数. 当一个函数/过程没有使用return显示的定义返回值时,pytho ...

  8. C# 数值的隐式转换

    Debug2.Log(5/8.0f, 5.0f/8, 5/8);//output:0.625, 0.625, 0 隐式数值转换表

  9. 高性能迷你React框架anujs1.1.0发布

    本版本对setState与forceUpdate内部依赖的setStateImpl进行了重构,性能稳定在60pfs之上.并且将组件实例的所有内部方法与属性都改成以___开头. https://gith ...

  10. ViewParent 和 ViewManager

    ViewGroup 继承了 View  实现了两个接口  ViewParent 和 ViewManager 接口 ViewParent:定义了成为一个View的parent的一些“职能”,当paren ...