你的问题的答案是,Post
、ApplyUpdates
和Commit
完全不同,并且通常在数据库应用程序中发生在不同的位置(进程)和上下文中。
Post
和ApplyUpdates
都是客户端操作,而Commit
是一个SQL操作,可能需要在服务器端显式调用以完成事务。
如果考虑一个三层服务器,就能更容易地理解它们之间的区别。SQLite有点奇怪,因为它不是真正意义上的Sql Server,不能像设计用于响应来自不同机器上不同进程的调用的服务器那样使用(尽管它可以作为三层系统的后端进行这样的操作)。
最简单的传统三层架构通常是这样的:中间层Delphi服务器位于Sql Server(例如MS Sql Server)和客户端层之间,客户端层通常是在客户机上运行的Delphi程序。Borland/EMBA实现这一点的传统技术是DataSnap
。
客户端层通常包含一个TClientDataSet
(或第三方等效组件),通过中间层中与服务器特定的TDataSet
派生类从后端SQL服务器接收数据。虽然将数据从Sql Server传输到中间层通常涉及Sql Server上的事务,但一旦所有数据都加载到客户端层的CDS中,SQL Server上就没有挂起的事务了(除非您想要在服务器上保持事务打开状态,这不友好于服务器的其他用户,并且会消耗服务器上的锁资源,这是有限的)。
当您编辑CDS中的数据(或任何TDataset派生类,实际上),会将数据集置于dsEdit状态(请参阅TDataSetState的在线帮助)。所做的更改是暂时性的,这意味着它们可以在CDS中撤消,直到调用.Post保存它们到CDS的Data(对于TClientDataSet,在调用.ApplyUpdates之前,可回滚对客户端数据的更改)。请记住,在客户端层上调用.CDS时,Sql Server中没有挂起的事务(或至少不应该有)。
调用.Post不会导致更改传播回相应的中间层数据集。要启动此过程,请在客户端层CDS上调用ApplyUpdates,它会涟漪到与中间层的面向服务器的数据集接口的TDataSetProvider中。正是DataSetProvider(或更准确地说是与其关联的TSqlResolver)生成实际发送到SQL服务器以将更改应用于SQL数据库的SQL。因此,在标准的DataSnap 3层设置中,您无法直接控制是否调用Commit。
Commit
是Sql Server执行的SQL操作,是完成事务的两种可能方式之一(另一种是Rollback
)。例如,对于MS Sql Server,连接到服务器可能配置为自动将接收到的UPDATE
,INSERT
和DELETE
语句包装在隐式事务中。
您需要关注事务控制的程度取决于您正在使用的后端服务器以及应用程序对与其他使用服务器数据的并发性的要求。如果您对SLite的事务处理感兴趣,请查阅您使用的DBcomponents或其源代码的文档。
一些用于与真正的SQL服务器一起工作的Delphi组件库支持公开控制服务器端事务的设施,例如Interbase的IBX组件。
顺便提一下,在Delphi术语中,CachedUpdates
是从早已过时的BDE遗留下来的,这是Borland公司最初尝试为各种后端服务器提供通用数据库访问框架的努力。它存在于一些TDataSet派生实现中,并且(在我看来)不幸地在FireDAC中重新出现了,EMBA的最新跨数据库解决方案。