再谈 Firebird / Interbase 自增字段和WebService MIDAS 框架下的 ClientDataSet

Firebird数据库Firebird.dll供VB6使用:C++dll源码和VB6 Demo源码演示 仅一个Win32 dll (非COM, 可直接使用), 让VB6拥有强大而不复杂的Firebird数据库,包含C++dll源码和VB6 Demo源码演示 firebird是一个全功能的,强大高效的,轻量级,免维护的数据库。它很容易让您从单用户,单数据库升级到企业级的应用,火鸟是提供许多 ANSI SQL 标准功能关系数据库,提供优秀的并发性、 高性能和对存储的过程和触发器的功能强大的语言支持。 firebird是一个十分小的开源数据库,可作为像Access一样使用的文件型数据库,单用户连接;也能够以服务方式启动,支持多用户访问 立即下载

架构:

1. 数据库服务器:FireBird;

2. WebService 服务器端,采用 FireDAC 控件 + DataSetProvider;

3. WebService 客户端,采用 ClientDataSet 绑定到服务器端的 DataSetProvider;

4. 数据库表名:TEST,有2个字段:XUHAO, DESC;其中 XUHAO 是整数,我希望它是个顺序自增的字段,是主键,也是本文关注处理的对象。

代码需求

上述架构下,连接数据库的控件,采用 FireDAC 还是其它控件,和本主题无关。虽然 FireDAC 控件也能处理 FireBird 的自增字段,我之前有文章写这个 -- 请见:再谈 Firebird / Interbase 自增字段和 FireDAC 以及 ClientDataSet

但在三层 WebService 架构下,上述方法比较麻烦,用不上。

在上述架构下,有几个前提是必须的:

1. XUHAO 字段是主键,因此在 ClientDataSet1 里面,新增记录,不能空,必须填值。又因为它的值是数据库服务器赋予的,是自增的,因此在客户端的 ClientDataSet1 里面,新增记录,填入负数值作为填充。

2. 在 WebService 架构下,ClientDataSet 和服务器端的 DataSetProvider1 是绑定的。

3. 尽量少写代码;

4. 尽量减少网络来回和网络数据量。

解决方案

方案一:

1. FireBird 数据库里面,为自增值,创建一个【生成器】。

2. FireBird 数据库里面,创建一个存储过程,这个存储过程调用生成器,获得一个唯一的增加值。存储过程代码如下:

BEGIN
  /* Procedure body */
  NEW_XUHAO = GEN_ID(TEST_XUHAO, 1);
  SUSPEND;
END

3. 在 WebService 服务器端的 SoapDataModule 里面,放一个 FdStoreProc 这个是 FireDAC 的用于存储过程的控件。将这个控件指向数据库的上述存储过程。写一个函数名为 GetNewXuHao,函数里面执行这个存储过程,获得最新的自增值;

4. 服务器端的 DataSetProvider 的 BeforeUpdateRecord 事件写入代码:

procedure TtestAutoInc.DataSetProvider1BeforeUpdateRecord(Sender: TObject;
  SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind;
  var Applied: Boolean);
begin
  if UpdateKind = ukInsert then
    DeltaDS.FieldByName('XuHao').NewValue := GetNewXuHao;
end;

上述代码,利用数据库的存储过程,从数据库获得唯一的自增值,将来自客户端提交的新增字段的 XUHAO 字段值,修改为数据库产生的值。

4.1. 同时,设置 DataSetProvider1.Options 的 poPropogateChanges 设置为 True (设计期勾选上);

4.2. 因为在服务器端修改了 DataSetProvider1 里面的 DeltaDS 的 XUHAO 字段值,又设置了上述属性,则客户端 ClientDataSet1.ApplyUpdates(0) 提交后,会自动获得服务器端修改的值,自动将新增记录的负数值变为正确的值。

到此问题搞定。

方案二:

第一个方案,服务器端需要做不少事,写不少代码,去调用数据库的存储过程等。如果绕开服务器端直接操作数据库,则自增不存在。严重依赖服务器端代码。

对于 FireBird 数据库来说,可以做一个真正的自增字段。实现方法是:

A. 仍然需要一个生成器,用于产生顺序自增的数字;

B. 一个绑定到 Insert 新增记录的触发器,当数据库插入新纪录时,为记录产生一个自增值。触发器代码如下:

CREATE TRIGGER BI_LOG_XUHAO FOR "LOG"
ACTIVE BEFORE 
  INSERT
POSITION 0
AS
BEGIN
  NEW.XUHAO = GEN_ID(LOG_XUHAO_GEN, 1);
END;

实现了上述触发器,对于这个字段来说,就是个自增字段。只要增加一条记录,数据库就自动为这个新纪录自动插入一个最新的由生成器产生的唯一数字。和数据库之外的代码无关。

问题来了,客户端 ClientDataset1 插入一条记录并提交后,如何更新,获得数据库自己产生的自增值?

此时,方案一的办法不灵了。除非想办法获得数据库对应的新纪录的值。网上有一些方法,但毕竟麻烦也不易懂,而且代码和具体的数据库有关。

对于客户端来说:

1. 首先要做点事情,就是每增加一条新纪录,把 XUHAO 字段的值,自动赋值为负数,避免因为它是主键导致没有值带来的键值冲突异常。当然,要求用户手动输入也是可以的。自动的代码如下,在 ClientDataSet1 的 AfterInsert 事件里面写代码:

procedure TForm2.ClientDataSet1AfterInsert(DataSet: TDataSet);
var
  i: Integer;
begin
  i := ClientDataSet1.Tag - 1;
  ClientDataSet1.FieldByName('XUHAO').AsInteger := i;
  ClientDataSet1.Tag := i;
end;

2. 提交成功后,最简单的做法:ClientDataSet1.Refresh;就可以刷新。马上,就可以看到 XUHAO 自动新插入的记录的负数,变成了数据库对应该记录产生的新的自增数字。

但是,简单的 Refresh 的问题是网络数据流量大,尤其是当数据库里面记录特别多的时候。如果肯定该表不会有太多数据,可以采用这个简单办法,少写代码。

2.1. ClientDataSet1.Refresh 会清空当前记录;

2.2. 然后,从服务器端的 DataSetProvider 请求全部数据。这样带来网络流量大的问题。

解决网络流量的问题:

既然 XUHAO 是一个整数主键,那么,SQL 语句可以写成:

select * from TEST where XUHAO>:XUHAO

然后,运行服务器,在设计期 IDE 里面,右键点 ClientDataSet1,下拉菜单选择 Fetch Params,它自动获取到参数。参数存在 ClientDataSet1 的 Params 属性里面,如果获取成功,看属性面板对应项目就能看到。

然后在 ClientDataSet1 的 BeforeRefresh 事件里面,对参数赋值,服务器端的 SQL 语句自动获得该参数。只要赋值正确,抓取的数据就只是最新的数据,降低了网络数据流量。代码如下:

procedure TForm2.ClientDataSet1BeforeOpen(DataSet: TDataSet);
begin
  ClientDataSet1.Params[0].Value := -1
end;
procedure TForm2.ClientDataSet1BeforeRefresh(DataSet: TDataSet);
var
  i: Integer;
begin
  FData := ClientDataset1.Data;  //这个 FData: Variant; 全局的。
  CLientDataSet1.Last;
  i := ClientDataSet1.FieldByName('XuHao').Value;

  ClientDataSet1.Params[0].Value := i;
end;
procedure TForm2.ClientDataSet1AfterRefresh(DataSet: TDataSet);
begin
  ClientDataset1.AppendData(FData, True);

  with ClientDataSet1 do
  begin
    //刷新后,负数记录还在,对于负数记录新增的记录也拉回来了。因此要清除掉负数记录。
    First;
    while not Eof do
    begin
      if FieldByName('XuHao').AsInteger < 0 then
      begin
        Delete;
      end
      else Next;
    end;

    MergeChangeLog;
  end;
end;

上述代码解释:

1. OnOpen 事件,第一次打开,参数赋值 -1,获得全部记录;

2. BeforeRefresh 事件,获取当前最大编号,赋值给参数。这里使用了 LAST,所以必须要先把 XUHAO 作为索引,让它自动排序。这里我是设计期完成,因此没有设置索引的代码。

3. AfterRefresh 事件,因为只抓取了最新插入的记录,因此:A. 把原来的记录加回来;B. 把负数的记录删除掉。

到此完成。这个方法的好处是,所有代码是在客户端完成,服务器端的代码是正常的代码,可以应对任何需求。数据库完成自增,也无需服务器端的 Delphi 代码干预,耦合度更低。

中文版:InterBase/FireBird数据库编程从入门到精通 从来没有过这么一种数据库,能够像InterBase/FireBird一样富有激情。这是一种完全为程序员准备的数据库,就像瑞士军刀一样小巧、方便、实用。以往的数据库,不是太大太笨重(例如,Oracle、MS SQL、DB2),就是太简陋,功能不足(例如My SQL)。而InterBase/FireBird则是在两者之间找到了一个很好的平衡点,笔者不妨称之为“中型数据库”。随着硬件环境的不断发展,普通的个人电脑的计算能力越来越逼近并不太久以前的大型计算机的能力,这种趋势同时也大大推动了与此相适应的中型数据库的应用。中型数据库逐渐蚕食大型数据库的市场,这几乎是一个明显的趋势。随着软硬件条件的不断发展,很多大型数据库的很多极其复杂的特性,今天看来逐渐成为了不必要。今天的软件用户更加渴求“简单、实用、绿色”。InterBase/FireBird数据库几乎就是为这个宗旨而量身定制的。....................... 立即下载

相关推荐

大白话,Android Studio安装及其资源分享(离线gradle配置)

安装AndroidAtudio,并通过aliClound镜像与离线gradle配置,来跳过相对“繁文缛节”的过程,直接实现开发

wangzixuanemp的博客 3598

7 大开源数据库利弊全对比

1、CUBRID CUBRID 是一个很好的免费开源选择,专门针对 Web 应用程序进行优化,当复杂的 Web 服务需要处理大量数据并生成巨大的并发请求时,CUBRID 非常有用。这个解决方案是用 C 写的。 优点: 多粒度锁定 在线备份 用于开发语言的 GUI 工具和驱动程序: JDBC, PHP, Python, Perl, 和 Ruby. ...

顺其自然~专栏 2490

firebird数据库安装连接的一些常见错误及解决方法

firebird数据库安装连接的一些常见错误及解决方法

hcy19970721的博客 5504

dmx512协议c语言编程,DMX512协议+c程序代码.pdf

DMX512 协议1.协议简介DMX 是Digital MultipleX 的缩写 ,意为多路数字传输。DMX512 控制协议是美国舞台灯光协会(USITT)于1990 年发布的灯光控制器与灯具设备进行数据传输的工业标准 ,全称是 USITT DMX512(1990) ,包括电气特性、数据协议、数据格式等方面的内容。2. 电气特性和物理层2.1. 电气特...

weixin_39928993的博客 2543

Python、Selenium实现问卷星自动填写(内含适配个人问卷的方法)

使用Python、Selenium实现问卷星自动填写,内含适配个人问卷的方法。

DaenCode的博客 3837

推荐!DBeaver 开源免费 功能强大的 数据库管理工具

(后续,还是转回mysql了,直接用的mysql5.7,支持win7的32位。DBeaver是一个流行的开源数据库管理工具,支持多种数据库管理系统(如MySQL、PostgreSQL、Oracle、SQLite、Firebird等),并具有简单易用的用户界面和强大的功能,例如数据导入/导出、数据查询、视图管理、SQL编辑器等。所以想把mysql换成firebird,省了每次安装程序的时候还要安装MySQL。而且,中文有遇到乱码的问题。后来找了好久发现了DBeaver,可以连接不同的数据库,并导入导出数据。

MANYOUZSH的专栏 1247

GEO优化实战:用AnswerBit量化AI搜索可见度与品牌监控体系

生成式引擎优化(GEO)正取代传统SEO,成为品牌在AI搜索生态中获取可见度的关键。当用户习惯从“翻列表”转向“直接问AI”,品牌能否被生成式引擎识别、引用并正向推荐,直接决定了其在用户决策链条中的存在感。AI搜索可见度因此从模糊概念演变为可度量的运营指标,涵盖提及率、引文率、情感分与回源质量等维度。腾讯AnswerBit作为答案侧分析工具,帮助运营者拆解AI回复中的品牌语境与引用来源,让优化动作有据可循。从内容结构化改造、品牌实体建设到第三方权威背书,GEO要求团队建立“度量-优化-再度量”的闭环。文章结

weixin_31100517的博客 150

Firebird 数据库使用心得

      本人想做一个桌面应用,需要一个免安装的嵌入式关系数据库,在对比了 Access 和 Firebird 之后,选择了更简便、性能更好的后者。Firebird 简介:      firebird是一个真正的关系数据库,支持存储过程、视图、触发器、事务等大型关系数据库的所有特性,它是一个开源的,可以自由使用的数据库(即使是商业上的使用)。具有以下的特点:  支持原

HiSpring的专栏 9059

Transformer实战(1)——词嵌入技术详解

词嵌入的核心思想是,通过将词语表示为稠密的向量,使得计算机可以更有效地处理和理解文本中的语义关系。在本节中,我们学习了单词分布式表示的概念及其实现,包括静态嵌入和动态嵌入,实现了 Word2Vec 和 GloVe 模型,并介绍了如何使用 Gensim API 探索嵌入空间。

盼小辉丶的博客 1万+

【C#程序员入门AI】必知的一些知识

2026年C#调用AI,核心就4个概念+3种方式4个概念:大模型(大脑)、嵌入(数字密码)、向量(载体)、Agent(超级助理)3种方式:云端API(快)、本地模型(隐私)、混合部署(最佳)不用怕复杂,跟着这个思路走,你就能从“AI小白”变成“C# AI开发能手”,把AI集成到你的.NET项目里,提升效率、创造价值!

人工智能AI技术 409

Linux下的FireBird 数据库

Linux下的FireBird 数据库   2000年7月,Borland(即现在的Inprise)公司公布了其数据库产品Interbase的源代码。Firebird数据库就是从该数据库 中派生出来的。当时,Interbase是与客户/服务器版本的 Delphi产品捆绑在一些销售的。现在,Interbase已经变成了一只开放源码中的“火鸟”。   为什么要使用Firebird?   也许...

代码民工 1156

零基础速成simulink代码生成——stateflow基础3

此专栏面向嵌入式工程没有matlab开发经验的人,可以快速学习和实践这门技术。MDB技术,越来越成熟和普遍,从手写代码转到基于模型开发已经是大势,不仅减少开发周期,还增加代码的复用性。汽车领域、医疗和算法建模广泛使用。

不断debug,优化中…… 1711

FIREBIRD浅历

firebird可以说是这个世界上最小而又支持存储过程的数据库,才3M而已,如果做小型应用,比ms sql(桌面版也有70多M),mysql(20-30M),方便的多。(一)数据库操作在开始-程序-Firebrid_2_0中执行Firebrid ISQL tool 出现SQL>输入SQL>CREATE DATABASE ‘e:/sams.fdb; 回车提示错误,……..,郁闷,一查资

godson_h的专栏 4409

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

现阶段的主流数据库分别是哪几种?

缓存一般用来保存一些进程被存取的对象或数据,通过缓存来存取对象或数据要比在磁盘上存取快很多,前者是内存,后者是磁盘、Memcached是一种纯内存缓存系统,把经常存取的对象或数据缓存在memcached的内存中,这些被缓存的数据被程序通过API的方式被读取,memcached里面的数据就像一张巨大的hash表,数据以key-value对的方式存在。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

2950

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【转】Firebird数据库值得信赖吗?为什么我要在开发中选择它?

Firebird数据库值得信赖吗?为什么我要在开发中选择它? 1、Firebird是一个真正的关系数据库,支持存储过程、视图、触发器、事务等大型关系数据库的所有特性;2、Firebird支持SQL92的绝大部分命令,并且支持大部分SQL99命令,新版Firebird 2.0对SQL99的支持更完整;3、Firebird源码基于成熟的商业数据库Interbase,有良好的稳定性,与Interbase有良好的兼容性;4、不用考虑授权费用(免费),不用当心将来有一天你或你的客户因为使用盗版而被数据库开发商告上法庭

Tirecoed的专栏 1669

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

数据库选型和FireBird的使用

<br />最近因为要做一个小的 项目,开发工具为Delphi,数据库选型进行了一些比较,最终决定采用FireBird数据库,各种数据库的优缺点分析如下:<br /><br />一、Firbird<br /><br />优点<br />1、Firebird是开 源免费的数据库,且诞生很多年了,比较稳定。<br />2、支持单机嵌入式开发, 单机版支持存储过程和触发器。<br />3、单机版和服务器版数据 库文件格式相同,升级至网络版简单。<br />4、跨平台,支持 window、linux<br

无名剑 1925

NonSQL数据库简介

<br />转自:http://blog.youkuaiyun.com/kk5595/archive/2011/01/04/6115950.aspx<br />【IT168 评论】 几乎每个Web开发人员都有自己喜欢的数据库,或自己最熟悉的数据库,但最常见的无外乎以下几种:<br />  MySQL<br />  PostgreSQL<br />  MSSQL<br />  SQLite<br />  MS Access<br />  或是更简单的XML,文本文件等。这些数据库有优秀的文档,背后有强大的社区支持,大部分

1030

FireBird Embedded学习日记

FireBird Embedded学习日记,有些内容还不太理解,欢迎大家指正.

u013727899的博客 8052

使用FireBird数据库基本知识

1.进安装目录bin文件夹,如果是3.0版本到根目录即可 2.数据库用户管理,使用命令:gesc -user sysdba - password masterkey    添加新用户:add huiqing -pw 123456 3.操作数据库:isql -user sysdba -password masterkey    创建数据库;create database 'c:\test.f

不敲代码的码农的博客 2万+

Firebird一款很牛X的数据库

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34297300的博客 1406

Borland DataSnap(MIDAS)三层架构编程中,DataSetProvider的Option属性

DataSetProvider的Option属性 看看远端数据模块里的DataSetProvider的Option属性是否设置正确!Provider控件的Options属性值是一个集合,用于设置有关打包和传递的选项,像显示哪些字段、允许哪种更新方式等等。1.         poFetchBlobsOnDemand:若包含此项,则表示数据包中不包括BLOB字段。不过,如果客户端的Tcl

abin30的专栏 1123

Delphi clientdataset的详细介绍

http://www.cnblogs.com/yplong/archive/2013/02/23/2923473.html delphi Midas SQLServer的自增字段的处理1.新增时,表中有自增字段,但是不希望用Refresh,直接ApplyUpdates直接看见自增字段的值在DataSetProvider.AfterUpdateRecord写如下代码 +

632

delphi clientdataset.appenddata不能用于有聚合字段的数据集

delphi xe7, 有两个cds(cds1, cds2), cds1.commandtext='select a.id,sum(b.price*b.qty) from table1 left join table2 on a.orderno=b.orderno group by a.orderno cds1的查询语句中有sum函数,查出的数据值正确的。 cds2.appenddata(cds1.data,true); 但是如果复制给cds2,就不正确了。 比如cds1的记录sum值是825,

g58521547的专栏 575
上一篇: Delphi 10.4.2 社区版开发的 APP 在 Google play 发布成功
下一篇: 虚拟机里的 MacOS 硬盘扩容
pcplayer
博客等级 码龄26年 633粉丝 284原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值