ImageVerifierCode 换一换
格式:DOC , 页数:34 ,大小:64KB ,
资源ID:6979319      下载积分:10 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.docduoduo.com/d-6979319.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(TClientDataSet控件的学习.doc)为本站会员(jinchen)主动上传,道客多多仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知道客多多(发送邮件至docduoduo@163.com或直接QQ联系客服),我们立即给予删除!

TClientDataSet控件的学习.doc

1、TClientDataSet控件继承自 TDataSet,其数据存储文件格式扩展名为 .cds,是基于文件型数据存储和操作的控件。该控件封装了对数据进行操作处理的接口和功能,而本身并不依赖上述几种数据库驱动程序,基本上能满足单机“瘦“数据库应用程序的需要。 1TClientDataSet 的基本属性和方法介绍 1)FieldDefs: 字段定义列表属性 开发者可通过单击属性编辑器中该属性编辑按钮,或在该控件上单击右键选择弹出菜单中的“Fields Editor“菜单进行字段编辑。设置完此属性后,实际上就相当于定义了表的结构;如果想装入已有的数据表的结构和数据,可通过单击右键选择弹出菜单中的“A

2、ssign Local Data“菜单,从弹出对话框中选取当前窗体中已与数据库连接好的数据集控件名称即可(当前窗体中必须已放置好要套用的数据集控件并打开激活) 。 使用注意: 对于自定义的字段名表,该属性编辑完后,该控件仍然无法打开。必须右键单击该控件,选择弹出菜单中的“Create DataSet“菜单,让该控件以上述编辑的字段列表为依据,创建数据集后,才能够被激活打开和使用。否则,会出现类似“ClientDataSet1: Missing data provider or data packet.“的错误(包括在运行期,运行期可调用该控件的 CreateDataSet方法,从而动态定义字段

3、和表) 。2) FileName 属性 说明:数据存储文件的名称。 因该控件是基于文件型的数据操作控件,因此,必须指定所操作的数据文件名称(默认扩展名称.cds) ,从而打开和激活该控件,进而进行数据编辑。 例 1:利用此属性打开指定的.cds 文件varPath: string;begin Path := ExtractFilePath(Application.ExeName); /取得可执行文件路径 CDataSet1.FileName := Path + test.cds; CDataSet1.Open;end; 3)CreateDataSet 方法 说明:该方法以 FieldDefs中

4、的字段名表为结构建立数据集,常用来进行动态定义表。 例 2:动态创建一具有姓名和年龄两个字段的数据集。/ 创建字段名表CDataSet.FieldDefs.Clear;with CDataSet.FieldDefs.AddFieldDef dobegin Name := Name; Size := 10; DataType := ftString;end;with CDataSet.FieldDefs.AddFieldDef dobegin Name := Age; DataType := ftInteger;end; /动态创建数据集 CDataSet.CreateDataSet; /激活和

5、打开该数据集 CDataSet.Open; 4)Open 方法 说明: 打开和激活数据集控件,从而进行数据编辑。 a. 如果指定了 FileName属性,则直接用 Open方法即可打开和激活该控件,见例 1。 b. 如果未指定 FileName属性,可使用例 2方法动态创建和打开数据集,进而操作数据。 5)LoadFromFile 和 SaveToFile 说明:从文件中装入表结构和数据以及存储数据到文件。该方法类似于 Word中的打开新文件和另存为的功能。 例 3:将数据集的数据存储到指定文件中CDataSet.SaveToFile(c:windowsdesktoptest.cds); 6)

6、.First(到首) ,Prior(向前),Next(向后),Last(到尾),Edit(编辑),CanCel(取消编辑),Post(保存),Insert(插入记录),Append(添加记录),Delete(删除) , “refresh”(数据刷新)等数据集常用方法 说明:当指定了 FileName属性时,其 Post方法可将数据存入指定的文件中,类似其 SaveToFile方法;如果未指定存储文件名,则 Post方法只将数据存储在 RAM中。其它方法,同一般数据集控件使用方法,略。 7).Filter, Filtered: 过滤筛选属性 说明:用于筛选指定条件的记录,用法同一般数据集控件,略

7、。 例 4:在已经激活打开的数据集中筛选性别为男性的记录CDataSet.Close;CDataSet.Filter := 性别= + 男 + ;CDataSet.Filtered := True;CDataSet.Open; 2使用 TClientDataSet控件的应用程序发布的注意事项: 如前所述,使用 TClientDataSet控件的程序发布时不需要任何数据库驱动程序,大大节省了安装文件的大小。但是,在发布程序时别忘了将 Windows系统目录下 midas.dll(257KB)与应用程序一起发布(运行必须) ,否则,程序仍然无法正常运行。 三、结束语 通过使用 Delphi中 TC

8、lientDataSet控件,既实现了应用程序可彻底脱离数据库驱动程序,也实现了常规数据集控件简单易用的特性,为编写“瘦“数据库应用程序提供了一种技术方法和手段。 上述程序在 Pwindows98,Delphi5 下测试通过。 TClientDataSet在三层结构中,TClientDataSet 的地位是不可估量的,她的使用正确与否,是十分关键的,本文从以下几个方面阐述她的使用,希望对你有所帮助.1. 动态索引procedure TForm1.DBGrid1TitleClick(Column: TColumn);beginif (not column.Field is Tblobfield)

9、 then/Tblobfield不能索引,二进制ClientDataSet1.IndexFieldNames:=column.Field.FieldName;end;2. 多层结构中主从表的实现 设主表 ClientDataSet1.packetrecord为-1,所有记录 设从表 ClientDataSet1.packetrecord为 0,当前记录3.Taggregates 使用 (1)在字段编辑中 add new field类型为 aggregates 后设置 expression(表达试) 设置 active:=true即可 使用 dbedit的 field为前者即可 (2)使用 Ag

10、gergates属性 add设计表达试 调用 showmessage(floattostr(ClientDataSet1.Aggregates.Count); showmessage(ClientDataSet1.Aggregates.Items0.Value);4. 在单层数据库中不要 BDE 使用 ClientDataSet代替 table,使用 ClientDataSet的loadfilename装入 cds 代替 table的 tablename的 db或者 dbf 原来的程序改造方法: 加一个 ClientDataSet,使用右键 assign locate data 后 savet

11、ofile,再 loadfromfile,后删除 table 将原连 table的 datasource设为 ClientDataSet 唯一注意的是:要将 midas.dll拷到 system或者当前目录5. 三层结构的公文包的实现方法 同时设定 1:filename(*.cds)2.remote server6. 可以对 data赋值(从另一个数据集取值)ClientDataSet2.Data:=ClientDataSet1.Data;ClientDataSet2.Open; 或者ClientDataSet2.CloneCursor(ClientDataSet1,true);ClientD

12、ataSet2.Open;7. 附加数据取得 客户程序向应用服务器请求数据。如果 TClientDataSet 的FetchOnDemand 属性设为 True, 客户程序会根据需要自动检索附加的数据包如 BLOB字段的值或嵌套表的内容。 否则, 客户程序需要显式地调用 GetNextPacket 才能获得这些附加的数据包。ClientDataSet 的 packetrecords设置一次取得的记录个数8.ClientDataSet 与服务器端 query连接方法 (1)sql 内容为空 ClientDataSet1.Close; ClientDataSet1.CommandText:=edi

13、t1.Text;/即 sql内容 ClientDataSet1.Open; 对于没有应用服务器设置 filter 如:country like A% filtered=true可实现 sql功能(2) 有参数 如服务端 query的 sql为 select * from animals where name like :dd 则:客户端 ClientDataSet var pm:Tparam;begin ClientDataSet1.Close; ClientDataSet1.ProviderName:=DataSetProvider1; pm:=Tparam.Create(nil); pm.

14、Name:=dd; pm.DataType:=ftString; ClientDataSet1.Params.Clear; ClientDataSet1.Params.AddParam(pm); ClientDataSet1.Params.ParamByName(dd).AsString:=edit1.Text ; ClientDataSet1.Open; pm.Free;end;9. 数据的更新管理(1)savepoint 保存目前为止数据状态,可以恢复到这个状态var pp:integer;begin pp:=ClientDataSet1.SavePoint; ClientDataSet1

15、.Edit; ClientDataSet1.FieldByName(姓名).asstring:=古话; ClientDataSet1.Post; table1.“refresh”; end; 恢复点 ClientDataSet1.SavePoint:=pp; (2)cancel,RevertRecord 取消对当前记录的修改,只适合没有 post的,如果 post,调用 RevertRecord (3)cancelupdate 取消对数据库所有的修改 (4)UndoLastChange(boolean),changecount 取消上一次的修改,可以实现连续撤消 参数为 true:光标到恢复处

16、 false:光标在当前位置不动 changecount返回修改记录的次数,一个记录修改多次,返回只一次 但 UndoLastChange只撤消一次 10. 可写的 recno 对于 Ttable和 Tquery的 recno是只读的,而TClientDataSet的 recno可读可写 ClientDataSet1.recno:=5;是设第五个记录为当前记录11. 数据保存 对于 table使用 post可更新数据 而 ClientDataSet1的 post只更新内存数据,要更新服务器数据要使用ApplyUpdates (MaxErrors: Integer),他有一个参数,是允许发出错误

17、的 次数,-1 表示无数次,使用 simpleobjectbroker时常设为 0,实现自动容错和负载平衡= 影响 ClientDataSet处理速度的一个因素TClientDataSet 是 Delphi开发数据库时一个非常好的控件。有很强大的功能。 我常常用 ClientDataSet做 MemoryDataSet来使用。还可以将ClientDataSet的数据保存为 XML,这样就可以做简单的本地数据库使用。还有很多功能就不多说了。在使用 ClientDataSet的过程中关于怎样提高处理速度这个问题,我就我个人的一点点体会和大家分享一下。 通常情况下我们一般都是用.ClientData

18、SetDataSourceDBComponent 这样的结构,处理数据的时候就直接操作 ClientDataSet。但是大多 DBComponet都会立即响应 ClientDataSet的变化。如果你是向 ClientDataSet中插入很多数据时候,DBComponent 就要响应几次,而且响应过程根据不同的控件,速度,过程数量都不一样。这样就影响了程序的执行效率。所以在对 ClientDataSet处理中,我是用 ClientDataSet.DisableControls和ClientDataSet.EnableControls方法:打开和关闭 DBComponent与ClientData

19、Set的数据显示关系。 例如:ClientDataSetDisableControls;.for I := 0 to 10000 dobeginClientDataSet.Append;.ClientDataSet.Post;end;.ClientDataSet.EnableControls. 这样做以后你会发现处理速度比以前没有使用方法的时候有成倍的提高。 ClientDataSet 的数据查找。 我所介绍的心得和技巧都是用 ClientDataSet来做范例,也可以应用于其他的一些 DataSet。废话就不多说了。我们还是先看代码,让后再总结。1.Scanning 扫描数据查找 这是最简单

20、最直接也是最慢的一种方法,遍历所有数据:procedure TForm1.ScanBtnClick(Sender: TObject);varFound: Boolean;beginFound := False;ClientDataSet1.DisableControls;Start;tryClientDataSet1.First;while not ClientDataSet1.Eof dobeginif ClientDataSet1.FieldsFieldListComboBox.ItemIndex.value =SearchText thenbeginFound := True;Break

21、;end;ClientDataSet1.Next;end;Done;finallyClientDataSet1.EnableControls;end;if Found then ShowMessage(SearchText + found at record + IntToStr(ClientDataSet1.RecNo)elseShowMessage(ScanForEdit.Text + not found);end;2.Finding 寻找数据 最老,但是最快的查找方式。 使用 FindKey/FindNearest来查找一条或多条符合条件的数据,当然待查找的 Field必须是一个 Ind

22、exField。可以看出,这种基于Index的查找速度是非常快的。procedure TForm1.FindKeyBtnClick(Sender: TObject);beginStart;if ClientDataSet1.FindKey(SearchText) thenbeginDone;StatusBar1.Panels3.Text := SearchText + found at record +IntToStr(ClientDataSet1.RecNo);endelsebeginDone;StatusBar1.Panels3.Text :=SearchText + not found;

23、end;end;procedure TForm1.FindNearestBtnClick(Sender: TObject);beginStart;ClientDataSet1.FindNearest(SearchText);Done;StatusBar1.Panels3.Text := The nearest match to +SearchText + found at record +IntToStr(ClientDataSet1.RecNo);end3.Going 定位GotoKey/GotoNearest 与 FindKey/FindNearest基本上没有什么区别。它也是基于 Ind

24、ex的查找。唯一的区别就是在于你是怎么定义你的查找了。代码上也有区别:ClientDataSet1.SetKey;ClientDataSet1.FieldByName(IndexFieldName).value := SearchText;ClientDataSet1.GotoKey; 就相当于ClientDataSet1.FindKey(SearchText); 要用好这两种基于 Index的查找,还需要了解 ClientDataSet和 Index机制。这里就不详细说明 Index机制。一个基本的原则,要有 Index,才能查找。4.Locating 查找数据2,3 两种查找方式都是基于

25、Index的,但是在实际应用中,可能会查找 IndexField以外的 Field。那我们就可以使用 Locate。但是查找速度是没有 2,3两种快的。比如:如果你查找一条纪录9000/10000,Locate 需要 500ms,Scanning 需要2s,FindKey 只要10ms(但是当你打开 ClientData的时候,建立 Index需要 1s) 。procedure TForm1.LocateBtnClick(Sender: TObject);beginStart;if ClientDataSet1.Locate(Field1,Field2,VarArrayOfvalue1,val

26、ue2, ) thenbeginDone;StatusBar1.Panels3.Text :=Match located at record +IntToStr(ClientDataSet1.RecNo);endelsebeginDone;StatusBar1.Panels3.Text := No match located;end;end; 小结:ClientDataSet 提供了好多种查找数据的方法。但是各自有其优缺点。 上面的例子中有 Start;和 Done,如果你有兴趣,可以加入计时点进行速度测试。Scanning 最简单,但是最慢,因为比较慢,还得使用ClientDataSet.D

27、isableControls和ClientDataSet.EnableControls方法(我在前面一片文章讲过)。Findkey/FindNearest(GotoKey/GotoNearest) 代码多,但是非常快。必须使用 Index,不同的是 Find需要的 Index是必须建立好的,而 Goto可以在第一次使用时建立 Index。Locate 使用最方便,不需要 Index,但是速度没有 Find快。Delphi做为一个快速应用开发工具,深受程序员的喜爱。其强大的组件功能,让程序员能够轻松、高效地完成常见的界面开发、数据库应用等功能。然而,帮助的相对缺乏,使得许多组件的功能并不为人们正

28、确地使用,究其原因,仍然是认识上的问题。对于 MIDAS开发中的核心部件,TClientDataSet 和 TDataSetProvider,由于资料的缺乏,人们在网上大多谈论的是李维的书籍内容。我有幸在BDN上见到了 Cary Jensen的 Professional Developer系列文章,详细阐述了 DELPHI的数据库开发技术。现节选出其中的ClientDataSet部分,与大家共同分享。ClientDataSet是一个功能强大的类,通过在内存中模拟表格,实现了其它数据集组件所不具备的强大功能。以往只在 Delphi和 C+ Builder企业版中才提供这个组件,如今,Borlan

29、d 的全部产品(包括最新的 Kylix)都集成了 TClientDataSet组件。TClientDataSet从类的继承关系上来看,是 TDataSet这个抽象类的子类,所以我们可以在 TDataSet这个抽象层次上对其进行我们熟悉的操作,比如导航、排序、过滤、编辑。要注意的是,TClientDataSet使用了一种全新的技术,它将所有的数据均放在内存中,所以 TClientDataSet是个只存在内存中的“虚拟表”,因此对数据库的操作是非常快的。在 PIII 850,512MB 的机器上对十万条记录进行建索引的操作,花费的时间少于半分钟。与一般的数据集组件不同,TClientDataSet

30、 使用的技术比较特别,本着高速度、低存储需求的原则,TClientDataSet 的内部使用了两个数据存储源。第一个是其 Data属性,这是当前内存数据的视图,反映了所有的数据改变。如果用户从数据中删除一条记录,则此记录将从 Data中消失,相应地,加入一条新记录后,此记录便存在Data属性中了。另一个数据源是 Delta属性,故名思义,即增量的意思,这个属性反映了对数据的改变。无论是向 Data属性新增还是删除记录,都会在 Delta中记录下来,如果是修改了 Data中的记录,则会在Delta保存两条相应的记录,一条是原始记录,另一条仅包含修改的字段值。正因为 Delta的存在和 TClie

31、ntDataSet在内存中记录数据的特点,所有的改变都没有立即更新加对应的物理存储中,可以根据这些信息在适当的时候恢复,所以 TClientDataSet天生具有缓冲更新功能。为了使数据更新回数据存储源,我们要调用 TClientDataSet中对应的方法。如果 ClientDataSet与 DataSetProvider关联,那么仅需调用 TClientDataSet的 ApplyUpdates方法即可保存数据的更新,但如果 TClientDataSet没有对应的 TDataSetProvider存在,而是直接同文件关联,那么,这种方式是非常有趣的,我们在BriefCase模型中会再次讲解这

32、个问题。此时,如果使用TClientDataSet的 SaveToFile和 LoadFromFile,都会保留着Delta。调用 MergeChangeLog和 ClearChanges后,Delta 的内容才会被清空。只是前者是将 Delta的数据同 Data结合起来,将改变存储到物理介质上,而 ClearChanges则是一股脑儿全部清空,将数据回复到原始状态。大部分的应用都是将 TClientDataSet与TDataSetProvider结合使用的。两者联合使用的行为反映了Borland的设计宗旨,就是要提供一个面向分布式环境的思路。我们下面来慢慢解释。当我们将 TClientDat

33、aSet对象的 Active属性设为 True或者调用其 Open方法后,ClientDataSet 会向 DataSetProvider发送一个取数据包请求。于是 DataSetProvider便会打开对应的数据集,将记录指针指向第一条记录,然后从头到尾依次扫描。对于扫描到的每一条记录,都会将其编码成一个 variant数组,我们通常将它称之为数据包。完成扫描后,DataSetProvider 会关闭指向的数据集,并将所有的这些数据包传递给 ClientDataSet。在我提供的演示程序中,你可以清楚地看到这种行为(毕竟眼见为实吗!)。程序主界面右边的 DBGrid连接到一个指向数据库表的数

34、据源,DataSetProvider即指向此表。当选择了 ClientDataSet | Load菜单项时,你可以看到表格的数据被依次扫描,一旦到达最后一条记录,表格便会被关闭,右边的 DBGrid被清空,而左边反映ClientDataSet数据的 DBGrid便出显示出内存中的数据来。由于这个过程会在 DBGrid上反映出来,所以不到 1000条记录的取出时间中,大部分都浪费在屏幕的更新显示上了,你可以选择ClientDataSet | View Table Loading来禁止显示,而达到加速的目的。在上面的描述中,我们没有提到一个重要的环节,即数据包是如何还原成表格的。那是因为 Data

35、SetProvider会将数据包中的元数据解码出来,根据元数据(我们可以理解为数据表的结构)便可以构造出与物理数据表一模一样的内存虚拟表。但要注意的是,尽管DataSetProvider指向的数据表可能有多个索引,但这些信息是不会放在数据包中的,换句话说,ClientDataSet 当中的数据默认情况下是无索引的。但因为 ClientDataSet具有与 TDataSet一致的行为,所以我们可以在此基础上根据需要重建索引。在 ClientDataSet中的数据被修改后,可以提交给物理数据表持久化这此改变。这个工作便是由 DataSetProvider完成的。内部工作原理是:DataSetPro

36、vider 创建一个 TSQLResolver的实例,这个实例会生成要在底层数据上执行更改的 SQL语句。详细地说,就是对修改日志中的每一条被删除、插入、更改记录生成对应的 SQL语句。这个语句的生成也可以由用户控制,DataSetProvider 的UpdateMode属性和 ClientDataSet中的 ProviderFlags属性都对SQL语句的生成有影响。当然,你也可以换一种方式,即采取同单机或 C/S结构一样的数据直接操作机制,绕过 SQL语句和缓冲更新机制来修改数据库。只需将 ResolveToDataSet属性设为 True,那么 DataSetProvider在持久化更新时

37、便不会使用 TSQLResolve,而是直接修改物理数据源。即定位到要删除的记录,调用删除语句,定位到修改记录,调用修改语句。我们可以对演示程序稍加修改,观察此种行为。请将演示程序中的 DataSetProvider的 ResolveToDataSet属性由 False改为 True,运行。在界面中修改数据并且保存,你将会看到右边的导航按钮会在瞬间变得可用。更绝妙的是,Borland 考虑到了应用的多样性,为我们提供了BeforeUpdateRecord事件,这样,当 DataSetProvider对每个修改日志的记录进行操作时,都会触发此事件,我们可以在此事件中加入自己的处理,如“加密操作”

38、、“商业敏感数据处理”等应用,从而极大地方便了程序员,让程序员对于数据具有完全的控制能力。分布式环境的复杂性对数据的存取提出了更高的要求,所以使用事务来保证数据的完整性和一致性是非常必要的,Borland 考虑到了这一点,当调用 ClientDataSet的 ApplyUpdates时,你可以传递一个整数值来指明可以容忍的错误数量。如果你的数据非常严格,则可以传递 0值,这样,DataSetProvider 在应用修改时便会打开一个事务,如果遇到错误,便会回退此事务,修改日志将保持原样,并且将出错的记录标记出来,最后会触发 OnReconcileError事件。如果传递了一个大于 0的数,则当

39、出现的错误数量小于此指定值时,事务会被提交,发生错误而导致提交失败的记录会保留在 Delta中,而提交成功的记录会从修改日志中删除。若错误数量达到指定值,则事务会回退,结果同整数值为 0的情况。如果值为负数,则会交所以可提交的数据都提交,不可提交的数据仍然保存在修改日志中,并将出错记录标记出来。虽然,Borland 是为了满足分布式编程的需要而设计了TClientDataSet,但在其它类型的编程环境中使用 ClientDataSet也具有积极的意义。首先,我们可以看到,由于数据均在内存中进行操作,而且仅在打开数据库取数据时和将修改持久到回数据库时,才有数据库开销,其它时间数据库为零,这样就极

40、大地增加了数据库的负荷,让数据库服务器能满足更多用户的连接请求。其次,ClientDataSet具有其它数据集所不具备的许多高级功能,这为程序员进行复杂的编程提供了便利,可以不考虑数据库本身是否支持这此功能,而让 ClientDataSet去处理这些复杂而繁琐的细节。最后,ClientDataSet 在数据存储和应用程序间起到一个抽象层的作用。假如你的程序使用了 TClientDataSet,那么如果你以后要更改数据库存储机制。比如说由 BDE移植到 dbExpress,或者从 ADO移植到 Interbase Express,你的用户界面和数据控制部分几乎就不用改变,只需要将 DataSet

41、Provider指向新的数据存取组件即可。顺便说一句,由于缓冲更新的存在,用户可能非常厌恶调用ApplyUpdates操作,那么你可以将此调用放入 AfterPost和AfterDelte中,让用户的操作更方便。 Midas攻略2009年 02月 28日 星期六 11:16系统的结构client端的 ClientDataset直接连接 Server端的 Provider,可以构成最简单的 Midas系统,但是这种系统的缺点是很明显的,1.需要在 Client上注册 appserver,就算你发现了可以写注册表,解决这个问题,仍然增加了部署的复杂性2.系统内部传输的数据,将被完全屏蔽,你基本上无

42、法做任何的调整对于大型系统来说,你更新了一条数据,可能 roundtrip跑了几个来回,而请求响应将是一次 roundtrip,3.ClientDataset和 provider的连接,你有两种解决方式,a,一个业务,一个 Cp对(ClientDataset,Provider),麻烦吧,而且是有状态的.b.只用一个 cp对,更改 ClientDataset.CommandText,来返回不同的数据,这样不能池化 appServer,性能严重影响,于是这里推荐的模型是client端使用 ClientDataset来做一个本地缓存表,界面的数据由ClientDataset来提供,而 ClientD

43、ataset的数据,仅通过调用WebService也好,Com+组件也好的方法,来得到数据,当用户更新时,本地传送 ClientDataset的 Delta给后端,做更新.server端使用 ClientDataset-Provider-Dataset来取得数据,返回 ClientDataset的 data给调用者,然后立刻释放或关闭,成为无状态的 appserver,更新时,将调用者传过来的 dealta,付给ClientDataset并做更新,然后也立刻释放或关闭.server端的实现GetData应用很简单,没有特别之处,重要的时在 UpdateData的情况,以一个例子为例,我们取得

44、table1的数据,返回给客户端,客户端可以对数据进行 cud操作(Create,Update,Delete),然后一次性提交更改,(叹,midas 的 delta真是好,我一直觉得这个是完美的),我们看看 Server在 UpdateData时应该如何写代码,其中的关键有1.Provider的 ResolveToDataset为 true还是 false2.Provider的 UpdateMode3.TField的 ProviderFlags的设置ResolveToDataset确定当你调用 ClientDataset.ApplyUpdates时,是由 ClientDataset来生成 sq

45、l语句,还是由 AdoQuery来生成,如果为 true的时候,将由 AdoQuery来生成,一开始,我的设置是adoQuery.Sql没有设置,任何东西,而是在ClientDataset.CommandText中设置了select * from table1 where 1=0,此处的 1=0 是为了打开 ClientDataset时不需要取得任何数据,此时将竟能执行 Create操作,生成正确的 Insert语句.update和 delete操作均会报“Unable to find record. No key specified“错误,究其原因,是因为使用 adoquery来做更新,但是

46、此时用了 where 1=0,adoquery中没有任何数据,而 adoquery的更新(即 dataset的更新)是基于存在的数据来生成 sql语句,于是出现该错误,当然一个解决方式是 where 1=1,这样,汗,你不会写这样的代码吧,也可以解析 delta来只取得需要做更新的记录,但是这样写代码太累了,于是将其设置为 false,设置为 false没有问题嘛?,当设置成 false时,有 clientdataset来做更新,其就算时 where 1=0 也能生成正确的 cud的 sql语句,但是看看 updatemode设置的不同,会产生什么效果,1.upWhereAll这样在构建 sq

47、l语句时,将生成 where 字段 1=值 1 and 字段 2=值2.and 字段 n=值 n的查询语句来做单条记录的更新,当然这种方式没有问题,但是如果表中有 datetime类型字段并且该字段不是null的化,你将找不到任何记录,(我是在 sqlserver2000上发现这个错误的,也许在其他数据库上并没有这个问题),需要舍弃2.upWhereChanged当你更新了 Col1和 col2时,生成“where col1=原值 1 and col2=原值 2“,看到问题了嘛?如果你的这个表中有这两个字段完全一样的多条记录,那么后果是多么的可怕.当然一个字段的情况也是这样,看看帮助有什么upWhereAll All columns (fields) are used to locate the record.upWhereChange

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报