Patch 函数
适用于: 画布应用 模型驱动应用 Power Platform CLI 桌面流
在数据源中修改或创建一条或多条记录,或者合并数据源外的记录。
使用 Patch 函数可以在复杂情况(如执行不需要用户交互的更新或使用跨多个屏幕的窗体)下修改记录。
要更轻松地更新数据源中的记录以进行简单更改,请改用 Edit form 控件。 添加 Edit form 控件时,可以向用户提供要填写的窗体,然后将更改保存到数据源中。 有关详细信息,请参阅了解数据窗体。
观看此视频,了解如何使用 Patch 函数:
概述
使用 Patch 函数可修改数据源的一条或多条记录。 可以在不影响其他属性的情况下修改特定字段的值。 例如,以下公式更改名为 Contoso 的客户的电话号码:
Patch( Customers, First( Filter( Customers, Name = "Contoso" ) ), { Phone: "1-212-555-1234" } )
结合使用 Patch 和 Defaults 函数可创建记录。 可以利用此行为生成一个屏幕,以供创建和编辑记录。 例如,以下公式为名为 Contoso 的客户创建记录:
Patch( Customers, Defaults( Customers ), { Name: "Contoso" } )
即使不需要使用数据源,也可以使用 Patch 来合并两条或多条记录。 例如,以下公式将两个记录合并成一个同时识别 Contoso 的电话号码和位置的记录:
Patch( { Name: "Contoso", Phone: "1-212-555-1234" }, { Name: "Contoso", Location: "Midtown" } )
描述
在数据源中修改或创建记录
要在数据源中使用这个函数,请指定数据源,然后指定一条基本记录:
- 要修改记录,基本记录必须来自数据源。 基本记录可能来自一个库的 Items 属性(在上下文变量中),也可能来自其他途径。 不过,您可以追溯到基本记录来自数据源。 这一点非常重要,因为记录中包含一些额外的信息,可以帮助您重新找到记录,以便进行修改。
- 要创建记录,请使用 Defaults 函数创建一条包含默认值的基本记录。
然后指定一条或多条更改记录,每条记录都包含用于替代基本记录中属性值的新属性值。 更改记录按照参数列表从头到尾的顺序进行处理,并且使用后者的属性值替换前者的属性值。
Patch 的返回值是要修改或创建的记录。 如果是创建记录,返回值可能包含数据源自动生成的属性。 但是,返回值不为相关表的字段提供值。
例如,使用 Set(MyAccount, Patch(Accounts, First(Account), 'Account Name': "Example name"));
,然后使用 MyAccount.'Primary Contact'.'Full Name'
。 在这种情况下,您不能生成全名。 要访问相关表的字段,请改为使用单独查找,如:
LookUp(Accounts, Account = MyAccount.Account).'Primary Contact'.'Full Name'
更新数据源时,可能会产生一个或多个问题。 将 IfError 和 IsError 与 Patch 中的返回值配合使用,以检测和响应错误,如错误处理所述。 您还可以使用 Errors 函数识别和检查问题,如使用数据源所述。
相关函数包括 Update 函数来替换整个记录,以及 Collect 函数来创建记录。 使用 UpdateIf 函数可以根据条件来修改多条记录的特定属性。
在数据源中修改或创建一组记录
Patch 还可用于通过一次调用创建或修改多个记录。
它不是传递单条基本记录,而是在第二个参数中提供一个基本记录表。 更改记录也是通过表提供,并且与基本记录一一对应。 每个更改表中记录的数量必须与基本表中记录的数量完全相等。
如果以这种方式使用 Patch 函数,结果值也会是一个表,并且其中的记录与基本记录和更改记录也是一一对应的。
合并数据源外部的记录
指定一条或多条要合并的记录。 记录按照参数列表从头到尾的顺序进行处理,并且使用后者的属性值替换前者的属性值。
Patch 返回合并的记录,并且不会修改其参数或任何数据源中的记录。
语法
在数据源中修改或创建记录
补丁(DataSource,BaseRecord,ChangeRecord1 [, ChangeRecord2 ,... ])
- DataSource –必需。 包含要修改的记录或用于包含要创建的记录的数据源。
- BaseRecord –必需。 要修改或创建的记录。 如果记录来自数据源,则会找到记录并进行修改。 如果使用 Defaults 函数的结果,则会创建记录。
- ChangeRecords –必需。 一条或多条记录,其中包含要在 BaseRecord 中修改的属性。 更改记录按照参数列表从头到尾的顺序进行处理,并且使用后者的属性值替换前者的属性值。
在数据源中修改或创建一组记录
补丁(DataSource,BaseRecordsTable,ChangeRecordTable1 [, ChangeRecordTable2 ,... ])
- DataSource –必需。 包含要修改的记录或用于包含要创建的记录的数据源。
- BaseRecordTable –必需。 要修改或创建的记录的表。 如果记录来自数据源,则会找到记录并进行修改。 如果使用 Defaults 函数的结果,则会创建记录。
- ChangeRecordTables –必需。 记录的一个或多个表,其中包含在 BaseRecordTable 中要修改的每条记录的属性。 更改记录按照参数列表从头到尾的顺序进行处理,并且使用后者的属性值替换前者的属性值。
合并记录
补丁( 记录 1, 记录 2 [,...])
- 记录 - 必需。 至少要有两条要合并的记录。 记录按照参数列表从头到尾的顺序进行处理,并且使用后者的属性值替换前者的属性值。
示例
修改或创建记录(在数据源中)
在以下示例中,您会在名为 IceCream 的数据源中修改或创建一条记录,该数据源包含此表中的数据,并且会在 ID 列中自动生成相应的值:
公式 | 说明 | 结果 |
---|---|---|
Patch( IceCream, LookUp( IceCream, Flavor = "Chocolate" ), { Quantity: 400 } ) |
修改 IceCream 数据源中的记录:
|
{ ID: 1, Flavor: "Chocolate", Quantity: 400 } 已修改 IceCream 数据源中的 Chocolate 条目。 |
patch(IceCream,defaults(IceCream), { flavor:“草莓”) } | 在 IceCream 数据源中创建一条记录。
|
{ ID: 3, Flavor: "Strawberry", Quantity: 0 } 已在 IceCream 数据源中创建 Strawberry 条目。 |
对上面的公式进行计算后,数据源最终会产生以下值:
合并记录(数据源外部)
公式 | 描述 | 结果 |
---|---|---|
补丁( { 名称:“James”,分数:90 }, { 名称:“Jim”,传递:true } ) | 合并数据源外的两条记录:
|
{ Name: "Jim", Score: 90, Passed: true } |
使用 As 或 ThisRecord
在公式中使用 As 或 ThisRecord 关键字可避免不明确的计算上下文。
在下面的示例中,请考虑 If
语句中的第一个查找。 (OrderID = A[@OrderID])
应将 OrderId
the in the lookup scope 与 OrderId
the A
collection in the scope 进行比较 ForAll
。 在此情况下,您可能希望 A[@OrderId]
解析为本地参数。 但这并不明确。
Power Apps 目前将左侧 OrderId
和右侧 A[@OrderId]
都解释为查找范围中的字段。 因此,查找时总是会在 [dbo].[Orders1]
中查找第一行,因为条件始终为真(也就是说,任何行的 OrderId
都等于其自身。)
ClearCollect(
A,
Filter(
'[dbo].[Orders1]',
OrderId = 8888888
)
);
ForAll(
A,
If(
LookUp(
'[dbo].[Orders1]',
OrderId = A[@OrderId],
"OK"
) = "OK",
Patch(
'[dbo].[Orders1]',
LookUp(
'[dbo].[Orders1]',
OrderId = A[@OrderId]
),
{
OrderName: "val1"
}
),
Patch(
'[dbo].[Orders1]',
Defaults('[dbo].[Orders1]'),
{
OrderName: "val2"
}
)
)
)
使用 As 或 ThisRecord
只要有可能,请使用 As 运算符或 ThisRecord 来消除左侧的歧义。 对于 上述场景,建议这样做。
当您的公式在同一个数据源或表上对 ForAll
、Filter
和 Lookup
使用多个范围时,范围参数可能会与其他地方的相同字段发生冲突。 因此,建议使用 As 运算符或 ThisRecord 解析字段名称并避免多义性。
例如,您可以使用 As 运算符在下面的示例中消除歧义。
ClearCollect(
A,
Filter(
'[dbo].[Orders1]',
OrderId = 8888888
)
);
ForAll(
A,
If(
LookUp(
'[dbo].[Orders1]' As B,
B.OrderId = A[@OrderId],
"OK"
) = "OK",
Patch(
'[dbo].[Orders1]',
LookUp(
'[dbo].[Orders1]' As C,
C.OrderId = A[@OrderId]
),
{
OrderName: "val1"
}
),
Patch(
'[dbo].[Orders1]',
Defaults('[dbo].[Orders1]'),
{
OrderName: "val2"
}
)
)
)
或者,您可以将 ThisRecord 用于相同用途。
ClearCollect(
A,
Filter(
'[dbo].[Orders1]',
OrderId = 8888888
)
);
ForAll(
A,
If(
LookUp(
'[dbo].[Orders1]',
ThisRecord.OrderId = A[@OrderId],
"OK"
) = "OK",
Patch(
'[dbo].[Orders1]',
LookUp(
'[dbo].[Orders1]',
ThisRecord.OrderId = A[@OrderId]
),
{
OrderName: "val1"
}
),
Patch(
'[dbo].[Orders1]',
Defaults('[dbo].[Orders1]'),
{
OrderName: "val2"
}
)
)
)
要详细了解 As 运算符和 ThisRecord 的用法,请参阅运算符文章。