使用多对多关系
当很多行具有同样的相关数据时,使用多对多关系可实现灵活跟踪。 与一对多关系不同的是,多对多关系没有主表的概念。 这种关系是完全对称的,您可以从多对多关系的任意一侧开始访问相关行的集合。 要继续使用 Contoso 工作区共享数据模型,以下部分借助桌面和桌面功能项目讲述了如何在画布应用中处理多对多关系。 下图展示了这一关系及对应数据。
每个桌面可以有多个关联的桌面功能行,每个桌面功能也可以关联多个桌面。 您可使用 ThisItem.'Desk Features' 表达式从桌面行访问桌面功能集。 从桌面功能行,您可使用 ThisItem.Desks 表达式访问与特定桌面功能相关联的所有桌面。
您可使用本表达式在库中显示每个桌面以逗号分隔的值列表,如以下示例所示。
要完成填充标签文本的任务,请将标签上的文本属性设置为以下公式:
Concat(ThisItem.'Desk Features', Name, ",")
您在使用本公式时,要注意性能影响,尤其是当您有多条记录时,因为数据是从 Dataverse 访问的。 下图显示,已从监视器完成对 getRows 的一次调用,以获取办公桌列表。 对于每个桌面,都对 getNavigatedRowInTableRow 进行了调用,以检索办公桌功能。
此外,您可能会发现仅在用户在库中选定单个桌面行或深入挖掘桌面行详细信息后才显示桌面功能更好。
除此之外,还有一种使用本关系的方法是允许用户挑选桌面功能,然后使用 controlName.Selected.Desks 属性填充库中的项目。
本方法非常适用于仅允许在组合框中做出单项选择的情况。 如果启用多项选择,本逻辑会非常复杂。 目前,Power fx 还没有比较简单的方法来表达两个集合的交集,而这是本应用场景发挥作用的必要条件。 有变通方法可行。 例如,您可以迭代浏览所有选定功能,在单个集合中收集相关办公桌,删除重复项,然后使用该集合作为项目源。 但是,因为有多个 Dataverse 请求(每个选定功能一个),所以随着表的增加,本方法的性能也将迅速下降。
建立关系
建立多对多关系的主要方式是使用 Relate () 函数,这一点与一对多关系类似。 主要区别在于,不用管哪一条记录是 Relate() 的第一个或第二个参数,因为此关系没有主表。
管理窗体上的多对多关系比管理多对一查找列要复杂得多。 字段列表支持多对多关系;但是当您添加字段到窗体中时,系统不会生成公式让控件工作,而您也会收到类似以下示例的错误。
要解决这一问题,需更新多对多关系中另一侧表的项目属性中的 Choices() 函数。 为此,需从高级选项卡解锁卡。
在 Contoso 示例中,您希望使用桌面功能。 解锁该控件后,需验证项目属性是否显示以桌面功能为数据源。
注意
上述场景使用窗体来添加行。 要支持编辑功能,需确保将卡的 DisplayMode 属性从默认的查看设置更改为编辑。
调整好属性后,窗体用户界面便可正常工作,您也可从组合框中选择项目。 但是,如果您尝试提交窗体,则会收到类似以下示例的错误。
要解决这一问题,需清除更新属性,并在窗体提交后手动处理多对多关系。
清除更新属性后,窗体提交便可发挥作用。 但是,不会创建桌面与桌面功能表行之间的关系。 要建立关系,需将以下逻辑添加到默认用于提交窗体的复选图标的 OnSelect 属性中:
将在组合框中选择的桌面功能保存为一个集合。 这一步必须执行,因为提交窗体后,字段将会重置,值会丢失。
提交窗体。
使用保存的桌面功能集合来建立关系。
其他设计选项
用户在多对多关系中的体验与使用“选项”列时的体验类似。 选项值由创建者预先确定,并且不能禁用或固定。 因此,“选项”字段适合极少修改数据的场景,例如国家/地区列表。 此外,相关表中的行可在运行时停用、固定和添加。 本功能使得多对多关系非常适合在运行时需要一定灵活性的场景,比如您在为某个解决方案添加标签,而联系人与标签之间具有多对多关系,且标签需要由用户添加的情况。
多对多关系非常适用于您需要捕捉两表之间各行关系的情况。 各行之间的关系不能存储其他数据。 例如,如果您在联系人表和语言表之间建立了关系,您可能会追踪到某个人会说两种语言。
但您无从知晓这个人讲每种语言的时间及熟练程度。
常见的替代设计模式为创建您自己的相交表。 以下所用语言表是另一个自定义 Dataverse 表。 您可以针对描述特定关系的任何其他属性添加列至此表。 然后,这一新表与联系人表以及与语言表之间都将具有多对一关系。
处理应用中的这些表与处理具有一对多或多对一关系的其他表类似。 因为涉及额外的表,所以您可能会发现还需要一些额外逻辑来确保用户体验顺利。 务必要了解您的应用的要求,并且要知道多对多关系是否需要跟踪其他数据,尤其要考虑到您需要在表相关时做出本项决定。