【问题标题】:OppRecordCombo: execution of BeforeUpdate caused by: System.FinalException: SObject row does not allow errors ()OppRecordCombo:BeforeUpdate 的执行导致:System.FinalException:SObject 行不允许错误()
【发布时间】:2020-11-06 03:03:50
【问题描述】:

我在 Opportunity 对象上为插入前和更新前创建了一个触发器,通过它我将 Trigger.newMap 变量作为参数发送到我的 apex 类,在该类中我正在检查是否存在特定组合中的记录如果不存在特定的记录模式,则另一个称为记录组合的对象会尝试添加错误。但是当我尝试创建一个机会或更新它时,我得到了以下异常。

OppRecordCombo: execution of BeforeUpdate caused by: System.FinalException: SObject row does not allow errors () 

我的触发器在下面

trigger OppRecordCombo on Opportunity (before insert, before update) {
    if((Trigger.isBefore && Trigger.isInsert) || (Trigger.isBefore && Trigger.isUpdate)) {
        OppRecordComboClass opp = new OppRecordComboClass();
        opp.checkComboValidate(Trigger.newMap);
    }
}

我的顶级课程如下

public without sharing class OppRecordComboClass {
    //private List<Opportunity> opportunities;
    String recordComboString;
    String oppComboString;
    List<String> recordComboStringList = new List<String>();

    public OppRecordComboClass() {
    }

    public void checkComboValidate(Map<Id, Opportunity> opportunities) {
        try {
            List<Record_Combination__c> recordcombo = [SELECT Client__r.Name,
                                                            Client_SFDC_ID__c,
                                                            Agency__r.Name,
                                                            Agency_SFDC_ID__c
                                                            FROM Record_Combination__c];

            for(Record_Combination__c recComb : recordcombo) {
                recordComboString = recComb.Client__r.Name + recComb.Client_SFDC_ID__c + recComb.Agency__r.Name + recComb.Agency_SFDC_ID__c;
                recordComboStringList.add(recordComboString);
            }

            List<Opportunity> oppCheckList = [SELECT Id,
                                                    Account.Name,
                                                    AccountId,
                                                    Agency_Name__r.Name,
                                                    Agency_Name__c,
                                                    Allow_New_Account_Combination__c
                                                    FROM Opportunity
                                                    WHERE Id in :opportunities.keySet()];

            for(Opportunity opp : oppCheckList) {
                if(opp.Allow_New_Account_Combination__c == false) {
                    oppComboString = opp.Account.Name + opp.AccountId + opp.Agency_Name__r.Name + opp.Agency_Name__c;
                    System.debug('This is the opp combo string akki ' + oppComboString);
                    if(!recordComboStringList.contains(oppComboString)) {
                        //Opportunity triggerOpp = opportunities.get(opp.Id);
                        opportunities.get(opp.Id).addError('This Customer and Agency combination doesn\'t exist in OB. Do you still want to create this Opportunity');
                    }
                }
            }
        } catch(Exception e) {
            System.debug('An exception occured at the line ' + e.getLineNumber() + ' exception is ' + e.getMessage());
        }
    }
}

谁能告诉我为什么会发生这种情况以及如何纠正?

【问题讨论】:

    标签: exception error-handling salesforce


    【解决方案1】:
    1. 不要将trigger.newMap 传递给您的方法。这个变量是Map&lt;Id, Opportunity&gt;when you are before insert ids don't exist yet(嗯,呃)。您没有地图的键,因此变量将为空并且您的逻辑将被跳过。改为传递trigger.new
    2. 不要SELECT ... FROM Opportunity WHERE Id IN : ...。您在那里拥有从触发器传递的“新”数据状态。如果您查询,您将获得此保存操作之前的旧数据,而不是用户现在编辑的数据。或者什么都没有(因为如果你是before insert - 数据库中还不存在东西)。在 trigger.new 上处理原件。
    3. 你不能addError()你查询的东西。现在没有改变。 FinalException 不是一个好名字,但它告诉您将 addError 放在 trigger.new 的元素上

    【讨论】:

    • 在触发上下文中我没有得到父子实体的详细信息,对吗?例如,我想要 Account.Name,其中 account 是查找字段,它不会在 Trigger.New 上下文中传递。因此我不得不单独查询它。有什么解决办法吗?
    • 循环通过trigger.new,将Opportunity.AccountId收集到Set&lt;Id&gt;。在循环之外制作Map&lt;Id, Account&gt; accs = new Map&lt;Id, Account&gt;([SELECT Id, Name FROM Account WHERE Id IN :ids]);。再次循环通过 trigger.new 并引用它们,String accName = accs.get(opp.AccountId);
    • 你并不真的需要那个,是吗?在您的参考数据中,您还进行了关系查询。您的密钥可以有 id 而不是名称 0019E00001JLRluQAH;ABC001;a119E000002ObwYQAS。在调试日志中看起来不会那么性感,但性能更好,代码更简单。如果您有 2 个同名帐户,并且其中只有一个在允许的组合中 - 您会期望另一个帐户有机会通过吗? ;)
    • 第 1 条还是第 2 条评论?因为如果您决定使用第二个,如果它在 ID 而非名称方面效果很好 - 现在是回到最初的 VLOOKUP 想法并可能放弃整个事情的好时机:P
    • 我现在实际上正在处理第二条评论。正如你所提到的,我也会尝试研究并研究 VLOOKUP。
    猜你喜欢
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-01
    • 2018-11-20
    • 1970-01-01
    • 2017-02-03
    • 2020-08-29
    相关资源
    最近更新 更多