使用 Apex 触发器更新相关记录
Update related records with an Apex trigger
我有以下用例,但无法为其编写正确的触发器
在对象帐户上,我们拯救了我们的病人。每个病人都有一个相关的全科医生 (GP)。全科医生保存在联系人对象中。有时全科医生退休,新的全科医生接管全科医生,因此所有与该全科医生有联系的患者都必须更换新的全科医生。
我在 Salesforce 中创建了对象联系人 2 字段,GPChange__c(布尔值)和 NewGP__c(联系人查找字段)。当用户将布尔字段设置为 true 并填写新 GP 时,Apex 触发器必须 运行 并收集连接到 'retired' GP 的所有帐户(患者)并更新字段 GeneralPracticioner__c 帐户的 ID 来自 NewGP__C.
这是我到达的距离,它将 运行 并收集,但不会更新该字段。谁能帮帮我?
trigger trgnewGP on Contact (before update) {
for (Contact mycontact : Trigger.new) {
if (mycontact.GPChange__c = true && mycontact.NewGP__c != null){
list <account> gps = [SELECT GeneralPracticioner__c from account
where GeneralPracticioner__c =: mycontact.id];
for(Account acc : gps){
if (gps.size() > 0) {
acc.GeneralPracticioner__c = mycontact.NewGP__c;
} }
}
}
}
该代码中存在一些问题:
if (mycontact.GPChange__c = true ...
- 注意:您正在将 true
分配给 GPChange__c
。请记住,无需编写 checkboxField == true
,它已解析为布尔值。
- 没有dml,永远不会更新账户。
- 它没有批量化:您在循环内执行查询,因此它可能会抛出 LimitException(太多 SOQL 查询:101)
为了拉出查询,需要收集退休GP的Id。
然后你可以检索需要更新的帐户记录并使用 Trigger.NewMap.
设置 GeneralPracticioner__c
trigger trgnewGP on Contact (before update) {
List<Id> retiredGpIds = new List<Id>();
for (Contact gp : Trigger.new) {
if (gp.GPChange__c && gp.NewGP__c != null) {
retiredGpIds.add(gp.Id);
}
}
if (!retiredGpIds.isEmpty()) {
List<Account> patients = [SELECT GeneralPracticioner__c from Account WHERE GeneralPracticioner__c IN :retiredGpIds];
for (Account acc : patients) {
acc.GeneralPracticioner__c = Trigger.NewMap.get(acc.GeneralPracticioner__c).NewGP__c;
}
update patients;
}
}
由于联系人记录没有更新,我会 运行 在 after update
中触发此触发器。
更新:
The weird thing, when i try to use Dataloader [...] it works perfect and doesn't have any apex CPU errors.
Dataloader 使用批量 api,在异步上下文中 运行,因此它们具有更高的 CPU Limit:60 秒对 10 秒。
我建议在触发器处理程序 class 的 future
方法中提取该触发器的逻辑。
它应该看起来像:
@future
public static void updateGeneralPracticioner(List<Id> retiredGpIds) {
Map<Id, Contact> gpMap = new Map<Id, Contact>([SELECT Id, NewGP__c FROM Contact WHERE Id IN :retiredGpIds);
List<Account> patients = [SELECT GeneralPracticioner__c from Account WHERE GeneralPracticioner__c IN :retiredGpIds];
for (Account acc : patients) {
acc.GeneralPracticioner__c = gpMap.get(acc.GeneralPracticioner__c).NewGP__c;
}
update patients;
}
触发器:
trigger trgnewGP on Contact (after update) {
List<Id> retiredGpIds = new List<Id>();
for (Contact gp : Trigger.new) {
if (gp.GPChange__c && gp.NewGP__c != null) {
retiredGpIds.add(gp.Id);
}
}
if (!retiredGpIds.isEmpty()) {
ContactTriggerHandler.updateGeneralPracticioner(retiredGpIds);
}
}
@RubenDG
脚本完成了这项工作,非常好。但是当更多结果 >~100 条记录时,我得到一个 APEX CPU 时间限制。对象帐户上还有其他进程,但不是重型进程。为测试禁用了一些与帐户相关的其他 WF 规则或流程,但仍然得到 CPU 限制。我认为最大更新患者永远不会超过 1500...换句话说。没有全科医生的病人超过 1500 人。所以这不是很多。
Screenshot
奇怪的是,当我尝试使用 Dataloader 或 Workbench 并在帐户的字段 GeneralPracticioner__c 上执行更新(1200 条记录)时,它工作完美并且没有任何顶点 CPU 错误。
你有什么建议。编写一个异步的处理程序 class?使触发器异步(这甚至可能吗?)
我有以下用例,但无法为其编写正确的触发器
在对象帐户上,我们拯救了我们的病人。每个病人都有一个相关的全科医生 (GP)。全科医生保存在联系人对象中。有时全科医生退休,新的全科医生接管全科医生,因此所有与该全科医生有联系的患者都必须更换新的全科医生。
我在 Salesforce 中创建了对象联系人 2 字段,GPChange__c(布尔值)和 NewGP__c(联系人查找字段)。当用户将布尔字段设置为 true 并填写新 GP 时,Apex 触发器必须 运行 并收集连接到 'retired' GP 的所有帐户(患者)并更新字段 GeneralPracticioner__c 帐户的 ID 来自 NewGP__C.
这是我到达的距离,它将 运行 并收集,但不会更新该字段。谁能帮帮我?
trigger trgnewGP on Contact (before update) {
for (Contact mycontact : Trigger.new) {
if (mycontact.GPChange__c = true && mycontact.NewGP__c != null){
list <account> gps = [SELECT GeneralPracticioner__c from account
where GeneralPracticioner__c =: mycontact.id];
for(Account acc : gps){
if (gps.size() > 0) {
acc.GeneralPracticioner__c = mycontact.NewGP__c;
} }
}
}
}
该代码中存在一些问题:
if (mycontact.GPChange__c = true ...
- 注意:您正在将true
分配给GPChange__c
。请记住,无需编写checkboxField == true
,它已解析为布尔值。- 没有dml,永远不会更新账户。
- 它没有批量化:您在循环内执行查询,因此它可能会抛出 LimitException(太多 SOQL 查询:101)
为了拉出查询,需要收集退休GP的Id。
然后你可以检索需要更新的帐户记录并使用 Trigger.NewMap.
GeneralPracticioner__c
trigger trgnewGP on Contact (before update) {
List<Id> retiredGpIds = new List<Id>();
for (Contact gp : Trigger.new) {
if (gp.GPChange__c && gp.NewGP__c != null) {
retiredGpIds.add(gp.Id);
}
}
if (!retiredGpIds.isEmpty()) {
List<Account> patients = [SELECT GeneralPracticioner__c from Account WHERE GeneralPracticioner__c IN :retiredGpIds];
for (Account acc : patients) {
acc.GeneralPracticioner__c = Trigger.NewMap.get(acc.GeneralPracticioner__c).NewGP__c;
}
update patients;
}
}
由于联系人记录没有更新,我会 运行 在 after update
中触发此触发器。
更新:
The weird thing, when i try to use Dataloader [...] it works perfect and doesn't have any apex CPU errors.
Dataloader 使用批量 api,在异步上下文中 运行,因此它们具有更高的 CPU Limit:60 秒对 10 秒。
我建议在触发器处理程序 class 的 future
方法中提取该触发器的逻辑。
它应该看起来像:
@future
public static void updateGeneralPracticioner(List<Id> retiredGpIds) {
Map<Id, Contact> gpMap = new Map<Id, Contact>([SELECT Id, NewGP__c FROM Contact WHERE Id IN :retiredGpIds);
List<Account> patients = [SELECT GeneralPracticioner__c from Account WHERE GeneralPracticioner__c IN :retiredGpIds];
for (Account acc : patients) {
acc.GeneralPracticioner__c = gpMap.get(acc.GeneralPracticioner__c).NewGP__c;
}
update patients;
}
触发器:
trigger trgnewGP on Contact (after update) {
List<Id> retiredGpIds = new List<Id>();
for (Contact gp : Trigger.new) {
if (gp.GPChange__c && gp.NewGP__c != null) {
retiredGpIds.add(gp.Id);
}
}
if (!retiredGpIds.isEmpty()) {
ContactTriggerHandler.updateGeneralPracticioner(retiredGpIds);
}
}
@RubenDG
脚本完成了这项工作,非常好。但是当更多结果 >~100 条记录时,我得到一个 APEX CPU 时间限制。对象帐户上还有其他进程,但不是重型进程。为测试禁用了一些与帐户相关的其他 WF 规则或流程,但仍然得到 CPU 限制。我认为最大更新患者永远不会超过 1500...换句话说。没有全科医生的病人超过 1500 人。所以这不是很多。
Screenshot
奇怪的是,当我尝试使用 Dataloader 或 Workbench 并在帐户的字段 GeneralPracticioner__c 上执行更新(1200 条记录)时,它工作完美并且没有任何顶点 CPU 错误。
你有什么建议。编写一个异步的处理程序 class?使触发器异步(这甚至可能吗?)