OppRecordCombo:执行BeforeUpdate的原因:System.FinalException:SObject行不允许出现错误()

OppRecordCombo:执行BeforeUpdate的原因:System.FinalException:SObject行不允许出现错误(),exception,error-handling,salesforce,Exception,Error Handling,Salesforce,我在Opportunity对象上为before insert和before update创建了一个触发器,通过该触发器,我将trigger.newMap变量作为参数发送到apex类,在apex类中,我根据另一个对象(称为record Combines)中的记录检查特定组合的存在性,并尝试添加错误,如果某个特定的记录模式不存在。但当我试图创建一个机会或更新它时,我得到了以下例外 OppRecordCombo: execution of BeforeUpdate caused by: System.

我在Opportunity对象上为before insert和before update创建了一个触发器,通过该触发器,我将trigger.newMap变量作为参数发送到apex类,在apex类中,我根据另一个对象(称为record Combines)中的记录检查特定组合的存在性,并尝试添加错误,如果某个特定的记录模式不存在。但当我试图创建一个机会或更新它时,我得到了以下例外

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());
        }
    }
}
不共享类的公共类{
//私人名单机会;
字符串记录组合字符串;
字符串和组合字符串;
List recordComboStringList=新列表();
公共类(){
}
公共无效检查组合验证(映射机会){
试一试{
List recordcombo=[选择客户端名称,
客户号,
机构名称,
机构SFDC ID c
从记录_组合__c];
用于(记录组合记录:记录组合){
recordComboString=recComb.Client\uuuuu r.Name+recComb.Client\u SFDC\u ID\uuuu c+recComb.Agency\uuuu r.Name+recComb.Agency\u SFDC\u ID\uu c;
recordComboStringList.add(recordComboStringList);
}
列表检查表=[选择Id,
帐户名,
帐户ID,
机构名称,
机构名称,
允许新帐户组合
来自机遇
其中Id为:opportunities.keySet();
针对(Opportunity opp:opp检查表){
if(opp.Allow\u New\u Account\u composition\u c==false){
oppComboString=opp.Account.Name+opp.AccountId+opp.Agency\u Name\uuu r.Name+opp.Agency\u Name\uu c;
debug('这是opp组合字符串akki'+oppComboString);
如果(!recordComboStringList.contains(oppComboString)){
//Opportunity triggerOpp=opportunities.get(opp.Id);
opportunities.get(opp.Id).addError('OB中不存在此客户和代理组合。是否仍要创建此Opportunity');
}
}
}
}捕获(例外e){
System.debug('在'+e.getLineNumber()+'行发生异常,异常为'+e.getMessage());
}
}
}
有人能告诉我为什么会发生这种情况,以及如何纠正这种情况吗

  • 不要将
    trigger.newMap
    传递给您的方法。这个变量是
    Map
    和(嗯,duh)。您没有映射的键,因此变量将为空,并且您的逻辑将被跳过。传递
    触发器。改为新建
  • 不要
    选择。。。来自Opportunity,其中Id位于:…
    。这里有一个从触发器传递的“新”数据状态。如果您进行查询,您将获得此保存操作之前的旧数据,而不是用户现在编辑的数据。或者什么都没有(因为如果您在insert之前是
    ,则数据库中还不存在这些内容)。在
    触发器上处理原始触发器。新建
  • 您不能对所查询的内容执行
    addError()
    。现在没有改变。
    FinalException
    不是一个好名字,但它告诉您在
    trigger.new的元素上添加
    addError

  • 在触发器上下文中,我没有得到父实体和子实体的详细信息,对吗?例如,我需要Account.Name,其中Account是查找字段,它不会在Trigger.New上下文中传递。因此,我不得不单独查询它。有什么解决办法吗?通过trigger.new循环,收集
    Opportunity.AccountId
    集合
    。循环外make
    Map accs=new Map([从Id所在的帐户中选择Id、名称:ids])。再次循环trigger.new并引用它们,
    String accName=accs.get(opp.AccountId)0019E00001JLRluQAH;ABC001;a119E000002ObwYQAS
    。在调试日志中看起来不那么性感,但性能更好,代码更简单。如果您有两个同名帐户,并且其中只有一个帐户处于允许的组合中,您希望另一个帐户有机会通过吗?;)第一条评论还是第二条评论?因为如果你决定使用第二个,如果它很好用的话,是ID,而不是名字-现在是回到最初的VLOOKUP想法的好时机,可能会放弃整个事情:我现在正在处理第二个评论。正如你提到的,我也会尝试调查和研究VLOOKUP。