使用 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?使触发器异步(这甚至可能吗?)