触发将图像从子记录复制到父记录

时间:2014-01-21 14:16:26

标签: triggers salesforce apex

我正在尝试编写一个触发器,它将使用子对象上的RTA字段中的图像更新父对象上的RTA字段。

创建子对象时出现以下错误

  

Apex触发器Updateparent导致意外异常,请联系您的管理员:Updateparent:执行AfterInsert导致:System.StringException:无效ID:(.....图像显示在这里....)外部入口点。< / p>

信息

Man Utd是子对象 帐户是父对象 Image__c是子对象上的RTA字段 Copy_image__c是帐户上的RTA字段

这是触发器代码

trigger Updateparent on Man_Utd_1__c (after insert, after update) {

    Map<ID, Account> parentAccounts = new Map<ID, Account>();

    List<Id> listIds = new List<Id>();

    for (Man_Utd_1__c childObj : Trigger.new) {
        listIds.add(childObj.Image__c);
    }

    parentAccounts = new Map<Id, Account>([SELECT id, (SELECT ID, Image__c FROM Man_Utd_s__r) FROM Account WHERE ID IN :listIds]);

    for (Man_Utd_1__c manu : Trigger.new) {
        Account myParentAccounts = parentAccounts.get(manu.Image__c);
        myParentAccounts.Copy_image__c = manu.Image__c;
    }

    update parentAccounts.values();
}

任何人都可以建议如何纠正这个问题,或者是否有可能做到这一点?

3 个答案:

答案 0 :(得分:0)

编辑回答评论

这个对我有用,在null检查周围稍作修改。搏一搏?该字段在“帐户”和“联系人”上均称为Image__c

trigger rollupImage on Contact (after insert, after update) {

    Set<Account> parents = new Set<Account>();
    for (Contact child : trigger.new) {
        if(child.AccountId != null && child.Image__c != null){
            parents.add(new Account(Id = child.AccountId, Image__c = child.Image__c));
        }
    }

    if(!parents.isEmpty()){
        List<Account> toUpdate = new List<Account>();
        toUpdate.addAll(parents);
        update toUpdate;
    }
}

ORIGINAL

错误

一切都写在那里;)

List<Id> listIds = new List<Id>();

for (Man_Utd_1__c childObj : Trigger.new) {
    listIds.add(childObj.Image__c);    // boom happens here?
}

您将富文本区域值(带有编码图像的超长字符串)分配给Id变量(15或18个特殊字符串)

试试这样:

Set<Id> ids = new Set<Id>(); // Set will ensure we won't have duplicate values
for (Man_Utd_1__c childObj : Trigger.new) {
    ids.add(childObj.Account__c);
}

优化 - 第1轮

在第二个循环中,您将设置Copy_Image__c字段,但是在Account的本地副本(循环范围内的局部变量)上。我不确定在那里设置它会将更改传播到父acc(它可能是完整副本而不是对地图中项目的引用。您可以将其(parentAccounts.put(manu.Account__c, myParentAccounts))放回地图或只需直接进行图像分配:

parentAccounts = new Map<Id, Account>([SELECT id FROM Account WHERE ID IN :ids]);
// I've removed the subquery, you don't need it, right?

for (Man_Utd_1__c manu : Trigger.new) {
    if(parentAccounts.containsKey(manu.Account__c)){
        parentAccounts.get(manu.Account__c).Copy_image__c = manu.Image__c;
    }
}
update parentAccounts.values();

优化 - 第2轮

它看起来有点愚蠢 - 我们查询帐户但我们需要获取的是Id ...但我们已经知道Id了,对吧?所以 - 看这个“专业技巧”(因为我的同事是Man U的忠实粉丝而分享);)

trigger Updateparent on Man_Utd_1__c (after insert, after update) {

    Set<Account> parents = new Set<Account>();
    for (Man_Utd_1__c child : trigger.new) {
        if(child.Account__c != null){
            parents.add(new Account(Id = child.Account__c, Copy_Image__c = child.Image__c));
        }
    }

    if(!parents.isEmpty()){
        List<Account> toUpdate = new List<Account>();
        toUpdate.addAll(parents);
        update toUpdate;
    }
}

答案 1 :(得分:0)

注意:优化是编写触发器时的关键。

在编写触发器时,请确保遵循所有最佳做法:

关于触发的主题演讲:

  • 优化 - 我已经用大写和第一行指定了它,因为它是写逻辑时的关键所在
  • 正确的缩进和代码注释,以便任何使用相同代码的人都可以通过浏览注释轻松理解逻辑。确保在初始注释中更新lastModifiedBy行,以便有助于保留最后一次工作/最后更新的跟踪以及在哪个日期。最好在每一行保留适当的代码注释 - 仅在需要的时候
  • 具有正确名称的变量ex:如果列表类型为var,则为'lst'前缀或'List'后缀,然后是正确名称ex:lstContactsToInsert或lstContactsToUpdate
  • 始终创建一个单独的处理程序类,并且不要在触发器本身上写下所有逻辑'作为最佳实践'
  • 有适当的触发器上下文。知道何时通过触发器上的salesforce文档使用正确的触发器上下文。使用'Before'上下文如果可以使用它来处理,如果不是那么去'After'上下文,这样就可以限制DML了。

关于处理程序的主题演讲

  • 触发器提到的前3个步骤也适用于
  • 使用常用的私有方法编写逻辑并在其他方法中使用

关于TestClass的主题演讲:

  • 始终使用测试类中的“GENERIC TEST DATA CLASS”编写测试类。
  • 使用正确的测试方法名称,例如:test_Method_One'OR'testImageUpdates
  • 使用断言并测试所有用例 - 负面和正面测试

<强>#1。触发

   /**
    *   @TriggerName : ContactTrigger
    *   @CreatedBy   : Rajesh Kamath
    *   @CreatedOn   : 30-Nov, 2016
    *   @Description : Trigger to update the image on parent object 'Account' based on the child object 'Contact' 
    *   @LastModified: None
    */  
    trigger ContactTrigger on Contact(after insert, after update) {

        //Instantiate the handler class
        ContactTriggerHandler objContactHandler = new ContactTriggerHandler();

        /* Trigger Context */
        if(Trigger.isAfter) {

            //Fire on Insert
            if(Trigger.isInsert) {

                objContactHandler.onAfterInsert(trigger.new); 
            }

            //Fire on Update
            if(Trigger.isUpdate) {

                objContactHandler.onAfterUpdate(trigger.new, trigger.oldMap);
            }
        }
    }

<强>#2。处理程序

   /**
     *   @HandlerName   : ContactTriggerHandler 
     *   @TriggerName   : ContactTrigger 
     *   @TestClassName : ContactTriggerHandlerTest [Make sure you create this with the steps at the end of this handler] 
     *   @CreatedBy   : Rajesh Kamath
     *   @CreatedOn   : 30-Nov, 2016
     *   @Description : Trigger to update the image on parent object 'Account' based on the child object 'Contact' 
     *   @LastModified: None
     */  
    public with sharing class ContactTriggerHandler {

        /*
           @MethodName : onAfterInsert
           @Parameters : List<Contact> lstNewContactRecords
           @LastModifiedBy : None [Make sure when anyone updates even this line will be updated for help for other users who work on later phase]
        */
        public void onAfterInsert(List<Contact> lstNewContactRecords){

            //Call a common method where we have logic
            reflectChildImageOnParent(lstNewContactRecords, null);      
        }

        /*
           @MethodName : onAfterUpdate
           @Parameters : List<Contact> lstContactRecords, Map<Id, Contact> mapOldContactRecords
           @LastModifiedBy : None [Make sure when anyone updates even this line will be updated for help for other users who work on later phase]
        */
        public void onAfterUpdate(List<Contact> lstContactRecords, Map<Id, Contact> mapOldContactRecords){

            //Call a common method where we have logic
            reflectChildImageOnParent(lstContactRecords, mapOldContactRecords);     
        }

        /*
           @MethodName : reflectChildImageOnParent
           @Parameters : List<Contact> lstContactRecords, Map<Id, Contact> mapOldContactRecords
           @LastModifiedBy : None [Make sure when anyone updates even this line will be updated for help for other users who work on later phase]
        */
        private static void reflectChildImageOnParent(List<Contact> lstContactRecords, Map<Id, Contact> mapOldContactRecords){

            /* Local variable declaration */
            List<Account> lstAccountsToUpdate = new List<Account>();

            for(Contact objContact : lstContactRecords) {

                //Execute on insert and update
                if((Trigger.isInsert || (Trigger.isUpdate && objContact.Child_Image__c != mapOldContactRecords.get(objContact.Id).Child_Image__c)) && objContact.Account__c != null) {

                    //List of accounts to update
                    lstAccountsToUpdate.add(new Account(Id = objContact.Account__c, Parent_Image__c = objContact.Child_Image__c));                  
                }
            }

            //Update the account records
            if(!lstAccountsToUpdate.isEmpty()) {

                update lstAccountsToUpdate;
            }
        }
    }

可以参考您的用例。 如果有帮助,请标记为“最佳答案”

答案 2 :(得分:-1)

忠诚度 - 儿童对象

字段:

  1. lightingdata__Contact__c(关系)
  2. lightingdata__imagenims__c //图片字段
  3. 联络 - 家长Obj

    字段:lightingdata__Imagefromloyalty__c

    trigger loyaltytocon on Loyalty__c (after insert, after update) {
        Map<id, Contact> conlist;
            List<Id> idlist=new List<id>();
            for (Loyalty__c loy:trigger.new) {    
                idlist.add(loy.lightingdata__Contact__c);
            }
            conlist= new Map<id, contact>([select id, lightingdata__Imagefromloyalty__c from contact where id In : idlist]);
    
            for(Loyalty__c lo:trigger.new){
                contact con = conlist.get(lo.lightingdata__Contact__c) ;
                system.debug('con data' + con);
                con.lightingdata__Imagefromloyalty__c = lo.lightingdata__imagenims__c;
            }
         update  conlist.values();
    }
    

    在pareant对象字段中,它将返回该图像文件具有URL。 然后你可以创建一个公式,只需在表格中引用(lightingdata__Imagefromloyalty__c),它就会显示图像。