主从模式(Master/Detail mode)是指建立主表和从表关系的多个数据集集合模式。
1. 关系设置
要设置主从模式,必须有一个主表数据集(TDataSet)和一个从表数据集(TDataSet),且主表数据集关联一个数据源组件(TDataSource),并将从表数据集的MasterSource指向该数据源组件,最后设置关联字段。设置主从表之间关联字段有2种形式:
1、在从表数据集的SQL中设置外键,通过参数指向主表的字段,如:
//主表数据集 Master := TOraQuery.Create(Self); Master.SQL.Text := 'SELECT * FROM Department'; //从表数据集 Detail := TOraQuery.Create(Self); Detail.SQL.Text := 'SELECT * FROM Employee WHERE Dept_No = :Dept_No'; //设置数据源 MasterSource := TDataSource.Create(Self); MasterSource.DataSet := Master; Detail.MasterSource := MasterSource; |
SQL中的冒号(:)代表后面为一个变量,且该变量的名称要与主表的主键字段保持一致。
2、设置从表的MasterFields和DetailFields属性,如:
//主表数据集 Master := TOraQuery.Create(Self); Master.SQL.Text := 'SELECT * FROM Department'; //从表数据集 Detail := TOraQuery.Create(Self); Detail.SQL.Text := 'SELECT * FROM Employee '; //设置关联字段 Detail.MasterFields := 'Dept_No'; //主表主键 Detail.DetailFields := 'Dept_No '; //从表中对应主表主键的字段 //设置数据源 MasterSource := TDataSource.Create(Self); MasterSource.DataSet := Master; Detail.MasterSource := MasterSource; |
2. 数据获取
主从模式数据获取有2种模式:
1、传统模式
传统模式下,主从关系的数据集获取数据时,先开启主数据集,针对主数据集的每一条记录,从数据集根据关联字段去获取相应的从表数据。这样最大的诟病是主数据集记录有多少条,就需要执行多少次从数据集的查询,效率非常低下。
2、本地模式(LocalMasterDetail)
ODAC特有的本地主从关系模式,将主表数据集和从表数据集的所有记录一次性从服务器上获取下来,然后根据主从关系设置在本地对从表数据集的记录进行过滤。这样做最大的好处是减少了对服务器的开销,尤其是主表记录非常多的情况下,数据库的SQL执行数量非常少,效率非常高。
传统模式和本地模式各有优缺点,真是“熊掌与鱼”的关系。2种模式的设置取决于主数据集的Options.LocalMasterDetail,如果为True表示本地模式,如果是False为传统模式。
3. 更新
主从关系数据集如果是通过TDataSetProvider一次性打包给TClientDataSet处理,就可以一次性提交服务器进行数据保存,不用考虑主从关系及事务处理。但是如果使用ODAC进行处理,主从关系数据集的更新存在2方面内容:
1、本地更新,即在本地的数据处理。
在缓冲模式下,从表的CachedUpdates属性只有在主表的选项LocalMasterDetail设置为True时才有效。无论是缓冲模式还是传统模式,本地更新时支持从表插入时自动填写对应主表数据集中关联字段的值,缺点是不支持级联删除和编辑,即删除主表记录时,从表记录不跟随级联删除,更改主表关联字段值时,从表对应字段值没发生变化。这一切需要代码自己控制。
2、远程更新,即将本地更新提交数据库保存。
无论是缓冲模式还是传统模式,远程更新提交数据库时,ODAC不支持类似于TClientDataSet的统一数据提交功能,必须由代码开启连接的事务,依次提交主表数据集和从表数据集的修改,其提交顺序由代码控制。这样做有个最大问题:插入新记录时需要先提交主表数据集,然后提交从表数据集,删除记录时,需要先提交从表数据集,然后再提交主表数据集,否则从表数据集会报外键约束错误。如果插入和删除动作同时存在,则会产生矛盾。通过连接组件的ApplyUpdates方法进行统一提交也存在上述问题。
解决的办法只能由客户端程序控制,修改一条主记录及其从记录,必须保存后才能进行其他主记录操作的方式。好在主从数据集需要同时操作和保存多条主记录的情况非常罕见,所以这个问题也就不是很大了,只是客户端的控制要做好。