公式字段:循环引用
字段公式可以读取关联记录的字段,即使该记录属于同一张表。但它不能读取该记录上的自身字段:公式编辑器会拒绝它,并显示消息“Circular reference”。
示例
表 Groups 有一个指向自身的引用 Parent:子组通过它指向所属的组。公式字段 Members 选出某个国家的人员(Country filter),而子组必须从其所属组的成员中选取自己的成员:
Ninox
let country := 'Country filter';
let candidates := if Parent then Parent.Members else select People end;
candidates[Country = country]公式编辑器拒绝这段代码:“Circular reference: Members”。
原因
Ninox 按字段而不是按记录来推理。要编译 Members 的公式,它必须知道 Parent.Members 的类型,因此要编译 Members 的公式……而这正是它此刻在编译的公式。父记录永远不会是记录本身,这一点无关紧要:这种依赖在编译时就被拒绝了。
注意
同一个表达式通过编程接口(/query)求值时,或者放在另一个字段的公式中时,都不会报错。只有它所读取的那个字段的公式编辑器会拒绝它:因此,在别处测试成功并不能保证它会被接受。
解决方法:第二个字段
让 Members 在不读取父组的情况下计算其列表:
Ninox
let country := 'Country filter';
select People where Country = country然后把限制交给第二个公式字段 Effective members,它读取记录本身及其父记录上的 Members:
Ninox
if Parent then
let parentMembers := Parent.Members;
Members[contains(parentMembers, this)]
else
Members
endEffective members 读取 Members,但 Members 不读取 Effective members:不再有循环。在方括号内,this 指正在检查的人员;因此父记录的成员要事先读入一个变量。
须知
- 子组的
Members字段现在包含不属于该组的人员:所有显示或使用成员的地方(视图、按钮、全局函数)都必须读取Effective members。 - 循环也可能经过两个字段:读取
Parent.'Effective members'的Members会形成Members→Effective members→Members的循环。我们没有验证 Ninox 如何处理这种情况:请用同样的方法避免它。
