Delphi中带缓存的数据更新技术

一. 概念

  在网络环境下,数据库应用程序是c/s或者是多层结构的模式。在这种环境下,数据库应用程序的开发应当尽可能考虑减少网络数据传输量,并且尽量提高并发度。基于这个目的,带缓存的数据更新技术应运而生,其大致过程就是:应用程序将数据库中数据提取到客户端的缓冲区,在缓冲区中完成数据的修改、更新、以及新数据的插入等操作;等操作完成之后,在一个合适的时间,一次性的将数据提交给数据库,从而大大减少了网络流量,减小了数据库服务器的负载,提高了并发性能。

  应当说,这并不是太新的技术,在delphi等数据库前端开发工具较早期版本中,就已经对这种技术做出了的支持。但是笔者发现一些程序员并不注意这种技术的合理运用,依然停留在单机应用程序的思路下,导致所编出来的程序效率低下或者出现潜在的错误。因此有必要对该技术的优点、运用原则以及运用方法(以delphi为例)做一个总结。

  二. 优缺点

  带缓存的数据更新技术主要有如下几个优点:

  (1) 最大限度的减少了网络流量,减少了数据存取的时间。提高了客户端数据库操作人员的效率。

  (2)减轻了数据库服务器的负担,因为许多反复的更新、修改、删除操作可以在客户端的缓冲区内完成,最后只把结果提交给服务器。

  (3) 有效缩减事务(transaction)处理的时间,减少了并发事务的吞吐量。从而更能够保证数据库的一致性。

  我们可以举个例子来说明其优越性:数据库操作员往数据库中插入一条数据记录,但马上发现该记录不合要求,于是将该数据删除。这一过程,如果采用不带缓冲的数据更新技术,则服务器端将执行一次插入操作,一次删除操作,在客户端和服务器端进行往返两次的数据传输,而且如果此数据与其他的数据库表有级联关系,还必须考虑到数据的级联更新、删除、恢复等操作。如果采用带缓存的数据更新方法,则可以在客户端的数据缓冲区完成这两步互逆的操作,而不会给服务器端带来任何动作,不会产生任何网络数据传输以及数据的级联更新操作。由此可见带缓冲的数据更新技术的巨大优势。

  带缓存的数据更新有一个缺点就是因为数据是在客户端存放的,所以该数据如果被其它用户更改的话,会产生丢失修改等不一致状况,需要考虑其并发控制的细节,充分考虑那些多变的数据可能出现的不一致的情况。这种技术的运用需要一定的技巧与一定的思维转变。

  三. 运用原则

  任何技术的优越性都是在一定的环境中体现出来,带缓冲的数据库更新技术主要在以下几种情况下运用更有优势:

  (1) c/s或者多层的数据库应用的场合。这种情况下,可以有效降低网络流量。在单机情况下,该技术没有意义。

  (2)在多表的数据更新场合。例如主表/明细表(master/detail)结构的更新中,往往两个表的增删是相互影响的,那么在客户端完成两个表的所有更新之后,最后可以定义一个事务来提交所做的更新操作。这样便有效的缩短事务的时间,更好的保证了数据的一致性。

  (3)服务器负载能力有限的场合。如今,随着pc机的速度提高以及价格的降低,客户机和服务器的能力差别越来越小,服务器的服务能力相对地下降了。客观上要求从软件的角度来降低服务器的负担,而带缓冲的数据更新则通过客户端分担一部分更新任务的方式,降低了服务器的负担。

  (4)数据被同时更新的概率比较低的场合。如果数据库中同一条数据很可能在同一时段被多个用户更新,那么这种情况就不适合带缓存的更新,因为在这种情况下,容易产生数据的错误覆盖,从而导致数据的不一致。

  四. Delphi中的控制方法概述

  Delphi作为一个流行的数据库开发工具,具有丰富的数据库操纵功能。在带缓冲的数据存取技术上,delphi做出了很全面的支持。通常,delphi为用户提供了TTable和TQuery等几种存取数据库表的数据集控件;提供了TDBNevigator控件,可以对数据集进行增、删、改、查询等操作。在数据集的属性控件中有一个cachedUpdate选项,将这一项设为true,delphi即允许以缓冲的形式来存取该数据集,也就是说对数据集所做的更新操作不会立刻自动反映到数据库服务器,而只有调用实际提交的方法(如applyUpdates()等),delphi才将实际提交的数据反映到数据库,同时通过数据集的onUpdateRecord()方法,来定义在实际更新数据库表时需要同时进行的操作(如级联删除等)。这样就为我们自己来控制数据提交的步骤提供了方便,虽然这使编程的难度有所增大,但是在某些场合我们需要这样的灵活性。而且通过这种模式,确实大大减少了事务的长度、降低了网络流量、增加了应用程序的可靠性。下面我们举一个具体的应用模块来说明如何运用这种编程模式。

  五. Delphi程序举例

  (1) 应用背景说明

  假设我们做一个商品定单处理的模块。在这个模块中涉及三个数据库表:订单表Order(有订单号OrderID、金额SumMoney、日期date、客户姓名costomer等字段),订单明细表OrderDetail(有订单明细号detailID、订单号OrderID、商品编号CommondityID、数量amount、单价price等字段),库存表storage(有商品编号CommondityID、现有库存量stocks等字段)。其中,订单与订单明细表是一对多的关系,以订单号OrderID作为连接字段。每当新增一份订单的时候,都必须修改库存表,将卖出的相应商品的数量从库存中减去。

  (2)程序框架说明

  下面是一段delphi程序的框架,大致说明了如何运用缓存更新的编程模式。读者可以自己将本程序的功能进一步的完善。

unit Order;
{单元名称}
interface
uses
{引用的模块}
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,Forms,
Dialogs, Grids, DBGrids, ExtCtrls, DBCtrls, ToolWin, ActnMan,ActnCtrls,
ActnMenus, DB, DBTables;

Type
{声明的变量、添加的控件以及定义的方法和过程}
 TOrderForm = class(TForm)
 TBOrder: TTable;
 TBDetail: TTable;
 OrderDB: TDatabase;
 ActionMainMenuBar1: TActionMainMenuBar;
 DBNavigator1: TDBNavigator;
 DBGrid1: TDBGrid;
 procedure TBOrderAfterPost(DataSet: TDataSet);
 procedure TBDetailNewRecord(DataSet: TDataSet);
 procedure TBDetailUpdateRecord(DataSet: TDataSet;
 UpdateKind: TUpdateKind; var UpdateAction: TUpdateAction);
 procedure TBDetailAfterPost(DataSet: TDataSet);
 procedure FormCreate(Sender: TObject);
 private
 { Private declarations }
  public
  { Public declarations }
  end;
 
 var
  OrderForm: TOrderForm;

  implementation

  {$R *.dfm}
  {下面的内容为主要的程序框架}

 procedure TOrderForm.FormCreate(Sender: TObject);
 {将主表与明细表的缓存更新选项设为true}
 begin
  TBOrder.CachedUpdates:=true;
  TBDetail.CachedUpdates:=true;
 end;

 procedure TOrderForm.TBOrderAfterPost(DataSet: TDataSet);
  {在提交Order表的更新后,执行本过程内容,本过程实现对主表和明细表的实际提交的事务。
   注意:如果一个数据集的cachedUpdates属性为true,
    那么post这个动作仅仅是在客户端缓冲区中进行一个提交动作,
    而不是真正的提交给实际的数据库。要实现真正的提交,
    需要用到applyUpdates语句。}
 begin
  OrderDB.StartTransaction;//更新事务开始执行
  try
   TBOrder.ApplyUpdates;//对主表进行实际的更新
   TBDetail.ApplyUpdates;//对明细表进行实际的更新
  except
   Orderdb.Rollback;//如果发生意外,那么回滚这个事务,退出该过程
   exit;
  end;
  OrderDB.Commit;//如果没有发生意外,那么完成事务提交
  TBOrder.commitUpdates;//清空TBOrder表的客户缓冲区
  TBDetail.commitUpdates;// 清空TBDetail表的客户缓冲区

 end;

 procedure TOrderForm.TBDetailNewRecord(DataSet: TDataSet);
 {当新增一个明细表记录时所完成的动作。}
 begin
 TBDetail.FieldByName(‘OrderID‘).AsInteger:=TBOrder.FieldByName(‘OrderID‘).AsInteger;
 file://将主表的orderID字段赋给明细表的orderID字段,这个字段是两个表的关联字段

 end;

procedure TOrderForm.TBDetailUpdateRecord(DataSet: TDataSet;
 UpdateKind: TUpdateKind; var UpdateAction: TUpdateAction);
 {当实际更新数据库表时,需要同时进行的操作在onUpdateRecord事件中定义,
  在本例当中是进行明细表和库存表的级联更新操作。
  注意:在本过程当中所进行的操作是在实际更新数据库时所进行的动作,
   而不是更新客户端的缓存数据时所进行的动作}
 Var temp_query:TQuery;
 begin
  if UpdateKind=ukInsert thenfile://如果更新类型是插入一个新的记录,那么更新相应的库存量
   with temp_query do
   begin
    close;
   SQL.clear;
   SQL.add(‘update storage set stocks=stocks-:amount‘);
   SQL.add(‘ where commondityID=:commondityID‘);
   paramByName(‘amount‘):=TBOrder.FieldByName(‘amount‘).AsFloat;
   ParamByName(‘commondityID‘):=TBDetai.FieldByName(‘commondityID‘).AsInteger;
   execSQL; file://执行更新库存的sql语句,将相应的库存量减去。
  end;

 end;

 procedure TOrderForm.TBDetailAfterPost(DataSet: TDataSet);
 {当对明细表的记录进行修改,并提交(post)之后,执行本过程中的语句。
  注意:这种提交是针对客户端数据的,并没有真正反映到数据库中去。
  在本例当中,实现的功能是计算主表的总金额字段}
 begin
  TBOrder.FieldByName(‘money‘):=0;
  with TBDetail do
  begin
   first;
   while not eof do
   begin
    TBOrder.FieldByName(‘money‘):=TBOrder.FieldByName(‘money‘)+
    FieldByName(‘price‘).AsFloat*FieldByName(‘amount‘);
    file://将明细表的金额累加到主表的金额字段
   next;
  end;
 end;

end;

end.

原文地址:https://www.cnblogs.com/jijm123/p/10652699.html

时间: 2024-10-02 08:44:13

Delphi中带缓存的数据更新技术的相关文章

DELPHI中四种EXCEL访问技术实现

一.引言 EXCEL在处理中文报表时功能非常强大,EXCEL报表访问也是信息系统开发中的一个重要内容,本文总结以往开发中所用到的几中EXCEL文件访问方法,在实际工作中也得到了很好的验证,本文列举了其中四种方法的实例与读者共享,程序已在WINDOWS2000操作系统.OFFFICE2000应用软件和DELPHI7环境下调试通过. 二.ADO方式访问EXCEL文件 ADO方式访问EXCEL文件时,将EXCEL文件看作一个等同Oracle.MS SQLServer等数据库的一个ODBC数据源本文应用

Delphi 中的DLL 封装和调用对象技术(刘艺,有截图)

Delphi 中的DLL 封装和调用对象技术本文刊登2003 年10 月份出版的Dr.Dobb's 软件研发第3 期刘 艺摘 要DLL 是一种应用最为广泛的动态链接技术但是由于在DLL 中封装和调用对象受到对象动态绑定机制的限制使得DLL 在封装对象方面有一定的技术难度导致有些Delphi 程序员误以为DLL 只支持封装函数不支持封装对象本文着重介绍了DLL 中封装和调用对象的原理和思路并结合实例给出了多种不同的实现方法关键字动态链接库DLL 对象接口虚方法动态绑定类引用面向对象1 物理封装与动

java中的缓存技术该如何实现

1缓存为什么要存在?2缓存可以存在于什么地方?3缓存有哪些属性?4缓存介质? 搞清楚这4个问题,那么我们就可以随意的通过应用的场景来判断使用何种缓存了. 1. 缓存为什么要存在?一 般情况下,一个网站,或者一个应用,它的一般形式是,浏览器请求应用服务器,应用服务器做一堆计算后再请求数据库,数据库收到请求后再作一堆计算后把数据 返回给应用服务器,应用服务器再作一堆计算后把数据返回给浏览器.这个是一个标准流程.但是随着互连网的普及,上网的人越来越多,网上的信息量也越来越 多,在这两个越来越多的情况下

Delphi中线程类TThread实现多线程编程(线程同步技术、Synchronize、WaitFor……)

接着上文介绍TThread. 现在开始说明 Synchronize和WaitFor 但是在介绍这两个函数之前,需要先介绍另外两个线程同步技术:事件和临界区 事件(Event)与Delphi中的事件有所不同.从本质上讲,Event其实就相当于一个全局的布尔变量.它有两个赋值操作:Set和ReSet,相当于把它设置为 True或False.而检查它的值是通过WaitFor操作进行.对应在Windows平台上,是三个API函数:SetEvent.ResetEvent.WaitForSignalObje

蓝桥杯 地宫寻宝 带缓存的DFS

最近一个问题很困扰我,今天则得到了答案,也意味着我该选择了. 不知道大家有没有遇到过这样的情况,我是上年刚毕业,大四时进行过java培训,12年9月-13年4月,在这之前已经自学过java.7月份时进入一家公司工作,今年3月份辞职,4月份找到工作,来上班了.一开始就不太喜欢公司氛围,前台,hr,态度什么的都不太好,工作环境也极像客服部,整天电话不断,讨论声不断,第一个星期真是煎熬,去了两三天之后有辞职的想法,但是后面想想还是算了,公司待遇还可以. 但是进入到公司后leader让学PHP,学PHP

Delphi中window消息截获的实现方式(2)

Delphi是Borland公司提供的一种全新的WINDOWS编程开发工具.由于它采用了具有弹性的和可重用的面向对象Pascal(object-orientedpascal)语言,并有强大的数据库引擎(BDE),快速的代码编译器,同时又提供了众多出色的构件.受到广大编程人员的青睐.在众多的编程语言(如VB,PowerBuilder,Powerpoint等)中脱颖而出.其中一个DELPHI强于其他编程语言(如VB4.0)的地方就是在DELPHI中可自定义消息,并可直接处理消息.这对于那些希望编写自

[翻译]比较ADO.NET中的不同数据访问技术(Performance Comparison:Data Access Techniques)

Performance Comparison: Data Access Techniques Priya DhawanMicrosoft Developer Network January 2002 原文链接:https://msdn.microsoft.com/en-us/library/ms978388.aspx 概要:在典型的应用环境中,比较不同数据访问技术的表现性能.适用于Microsoft .NET Framework Beta2 和 Microsoft SQL Server 2000

Delphi中线程类TThread 实现多线程编程

作者:Rogee出处:Http://Rogee.cnblogs.com/心得:BLOG是什么,它是一个记录学习过程的东西 Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchronize的用法就完了.然而这并不是多线程编程的全部,我写此文的目的在于对此作一个补充. 线程本质上是进程中一段并发运行的代码.一个进程至少有一个线程,即所谓的主线程.同时还可以

教程-Delphi中Spcomm使用属性及用法详解

Delphi中Spcomm使用属性及用法详解 Delphi是一种具有 功能强大.简便易用和代码执行速度快等优点的可视化快速应用开发工具,它在构架企业信息系统方面发挥着越来越重要的作用,许多程序员愿意选择 Delphi作为开发工具编制各种应用程序.但是,美中不足之处是 Delphi没有自带的串口通信控件,在它的帮助文档里也没有提及串口通信,这就给编制通信程序的开发人员带来许多不便. 目前,利用 Delphi实现串口通信的常用的方法有 3种:一是利用控件,如 MSCOMM控件和 SPCOMM控件:二