用Table控件模拟关联表
其实不管是双向生成还是单向生成,都会产生关联表,对于性能有一定程度的影响,只是双向生成的时候尤甚。
所以要追求极致的性能,最好是在设置关联的时候,将关联表生成模式选择为“无”。
但是关联表确实给我们带来了很大的便利,我们岂能因噎废食?
可否鱼和熊掌兼得,既可以得到关联表的好处,又不影响性能呢?
完全可以,这就是本节要介绍的内容。
请首先请打开CaseStudy目录下的文件:模拟关联表.Table
该文件的产品表和订单表之间正常建立了关联,
所以可以充分享受关联带来的好处,例如使用表达式来统计和引用数据,在代码中使用GetParentRow和GetChildRows方法快捷定位或筛选出关联行。
由于在建立这个关联的时候,关联表的生成模式选择了“无”,不会像常规那样自动创建和显示关联表,所以此关联的存在,对于性能几乎没有影响。
但是我们用窗口和Table控件模拟了一个关联表,打开此窗口后,如果在产品表选择某产品,窗口中的Table控件可以自动显示出该产品的所有订单,表现得就像真的关联表一样。
由于这个“关联表”是模拟的,平时并不存在,打开窗口的时候出现,关闭窗口的时候自动消失,所以这个“关联表”对于性能的影响极微。
设计步骤:
1、在产品表和订单表之间建立关联,关联名为"po",注意关联表生成模式要选择为“无”:
2、在产品表新建一个窗口,窗口类型为停靠,停靠位置为底端。
3、插入一个Table控件,绑定到订单表,将其“作为副本”属性设置为True,“允许编辑”属性设置为True,“停靠”属性设为Fill。
4、窗口的AfterLoad事件设为:
Dim
t As Table = Tables("窗口1_Table1")此段代码确保打开窗口后,Tables("窗口1_Table1")只显示当前选定产品的订单。
5、关闭窗口设计器,回到产品表,打开表属性设置窗口,将其CurrentChanged事件代码设为:
If
Forms("窗口1").Opened() '一定要判断用于模拟关联表的窗口是否已经打开当我们在产品表选择不同的产品时,上述代码会判断窗口是否已经打开, 如果已经打开,则更新Tables("窗口1_Table1")的Filter属性,使其显示新选定产品的订单。
6、将订单表的DataRowAdding事件代码设置为:
If
CurrentTable.Name
= "窗口1_Table1" Then
'如果当前表是模拟的关联表
Dim r
As Row =
Tables("产品").Current
If r
IsNot Nothing
Then
e.DataRow("产品编号")
= r("产品编号")
End
If
End
If
当我们选择这个模拟的关联表,然后单击菜单中的增加行按钮时,上述代码会检查产品表中是否有选定行,如果有则新增订单自动继承此选定产品的产品编号。
如果没有这段代码,在模拟的关联表增加行时,新增行是看不见的,因为新增行的产品编号为空,而模拟的关联表只显示产品编号为选定产品的订单。
至此,我们用窗口的Table控件模拟出来的关联表,和真正的关联表一样,能够动态显示选定产品的订单,新增行也能自动继承选定产品的产品编号,不同的只是这个“关联表”的名称是Tables("窗口1_Table1"),而不是Tables("产品.订单")。
7、在产品表增加两个表达式列,分别为总销售量和总销售金额,总销售量的表达式:Sum(Child(po).数量),总销售金额的表达式为:Sum(Child(po).金额)
8、将订单表的DataColChanged事件代码设置为:
Select
Case e.DataCol.Name
Case
"产品编号"
Dim pr
As DataRow =
e.DataRow.GetParentRow("产品")
If pr
IsNot Nothing
Then
e.DataRow("单价")
= pr("单价")
End
If
End
Select
这样在订单表输入产品编号,会自动从产品表中找出对应的产品,然后取其单价填入到订单表的单价列中。
9、将产品表的DataColChanged事件代码设置为:
If
e.DataCol.Name
= "单价" Then
'更新未确认订单的单价
Dim drs
As List(of
DataRow)
drs = e.DataRow.GetChildRows("订单")
For
Each dr
As DataRow
In drs
If
dr("确认") =
False Then
dr("单价")
= e.DataRow("单价")
End If
Next
End
If
这样在产品表修改某产品的单价,系统会找出订购此产品的全部订单,然后并将未确认订单的单价更新为新的单价。
一点提示:
我们没有必要将关联表视为洪水猛兽,只有确实因为关联表过多,对性能有严重影响时,才可以考虑编码模拟关联表。