0

I updated my question as my trigger is failing because of some other trigger.

I created a trigger on Opportunity object, So i am trying to insert object1 and object2 records based on some condition. I am using object1 id in object2. In my code i used DML operation inside for loop can anyone help me how to avoid it.

public class TriggerHandlerClass {


    public static void updateValues(List<Opportunity> oppLst){
        List<Custom_Object_1 > object1 = new List<Custom_Object_1 >();
        List<Custom_Object_2> object2List = new List<Custom_Object_2>();
        List<Custom_Object_3> Object3Entry = [select Id, Label__c,Type__c, product__r.Name, product__r.Family, product__r.Description from Custom_Object_3 Where Label__c = 'Technology' ];


        map<Id, Custom_Object_1 > mapOpportunityIdToMR = new map<Id, Custom_Object_1 >();



        for (Opportunity objOpportunity : oppLst) {  
            if ((objOpportunity.field__C == 'SOmething') )

                Custom_Object_1 Ob1Reg = new Custom_Object_1 ();
                Ob1Reg.Name = objOpportunity.FirstName +' '+ objOpportunity.LastName; 
                Ob1Reg.closeDate__C =System.today()+90;

                mapOpportunityIdToMR .put(objOpportunity.Id, Ob1Reg);
                insert ob1Reg;

                Custom_Object_2 dealProd = new Custom_Object_2();
                dealProd.Amount__c = 450;
                dealProd.Line_Description__c = 'text';
                dealProd.lookupField_CustomObject_3__C = Object3Entry[0].ID;
                dealProd.lookupField_CustomObject_2__C = Ob1Reg.ID;
                object2List.add(dealProd);
            }
        }

        insert object2List;
       // insert mapOpportunityIdToMR .Values();


        List<Opportunity> oppLstToUpdate = new List<Opportunity>();

        for(Id opportunityId: mapOpportunityIdToMR.keyset())
        {
            oppLstToUpdate.add(new Opportunity(Id = OpportunityId, Custom_Object_1_lookup = mapOpportunityIdToMR .get(OpportunityId).Id));
        }
        // update Opportunity
        update oppLstToUpdate;

    }
}

Trigger :

TriggerHandlerClass.updateValues(Trigger.New);
  • 2
    It would be helpful to include the error message that you're seeing. Also, on the following line dealProd.lookupField_CustomObject_2__C = Ob1Reg.ID;, Ob1Reg.Id will be null until after you insert the record. – Derek F Jan 26 '16 at 20:14
2

There is a lot of information missing from your question:

  • What error are you getting exactly?
  • On what statement is your error happening? I assume it's on insert object2List?
  • What action triggers your trigger (before insert, before update, etc.)
  • The subject mentions parent and child objects. Are Custom_Object_1, Custom_Object_2, Custom_Object_3 child of Opportunity?

Having said that, I will take a guess.

  • If custom object 2 is a child of opportunity, you need to set the parent ID before the insert
  • If the trigger is a before insert, the parent record is not even present in the DB yet.

If you post more information, then I will try to update this answer.

Edit: after reading your comments, this is what you can do: loop twice, first inserting all obj1's, then inserting obj2's. Like this:

public class TriggerHandlerClass {

    public static void updateValues(List<Opportunity> oppLst){
        List<Opportunity> matchingOpps = new List<Opportunity>();
        List<Custom_Object_1> object1 = new List<Custom_Object_1 >();
        List<Custom_Object_2> object2List = new List<Custom_Object_2>();
        List<Custom_Object_3> Object3Entry = [select Id, Label__c,Type__c, product__r.Name, product__r.Family, product__r.Description from Custom_Object_3 Where Label__c = 'Technology'];
        map<Id, Custom_Object_1> mapOpportunityIdToMR= new map<Id, Custom_Object_1>();

        for (Opportunity objOpportunity : oppLst) {  
            if ((objOpportunity.field__c == 'Something'))
            {
                Custom_Object_1 Ob1Reg = new Custom_Object_1 ();
                Ob1Reg.Name = objOpportunity.FirstName +' '+ objOpportunity.LastName; 
                Ob1Reg.closeDate__C =System.today()+90;
                mapOpportunityIdToMR.put(objOpportunity.Id, Ob1Reg);
                matchingOpps.Add (objOpportunity);
            }
        }
        insert mapOpportunityIdToMR.values();

        for (Opportunity objOpportunity : matchingOpps) {  
            Custom_Object_1 Ob1Reg = mapOpportunityIdToMR.get (objOpportunity.Id);
            Custom_Object_2 dealProd = new Custom_Object_2();
            dealProd.Amount__c = 450;
            dealProd.Line_Description__c = 'text';
            dealProd.lookupField_CustomObject_3__C = Object3Entry[0].Id;
            dealProd.lookupField_CustomObject_2__C = Ob1Reg.Id;
            object2List.add(dealProd);
            objOpportunity.Custom_Object_1_lookup = Obj1Reg.Id;
        }
        insert object2List;
        update matchingOpps;
    }
}

This is the explanation:

  • I loop over the opportunities twice: once to insert all object 1's, and then to insert all object 2's (because the object 1's need to be in place)
  • In the second loop, I don't have to iterate over all the opps and find the matching ones. Since the condition is the same as in the 1st loop, I save the matching opps in a list and iterate over that subset of opps only.
  • Your final loop other opps, whereby you created a new opp to update the existing ones, has been merged into my second loop, so it becomes irrelevant.

This code has not been tested, so you need to make sure it compiles and you need to create good tests for it.

(Note that if I were to upload this code to my source control I would be refactoring it heavily to rename variables and extract methods, but that is beyond the scope of this answer)

I would start by creating good unit tests, asserting the right behaviour, then you can edit the code on this class and make sure it works the way you want. Good luck!

  • thanks for your reply I want to set Custom_Object_1 to Custom_Object_2 field "lookupField_CustomObject_2__C " in my code. . if I insert Custom_Object_1 inside for loop it is working. But i don't want to use DML inside forloop – Anjali Jan 26 '16 at 20:33
  • You didn't supply any of the information I was asking :(. A lookup field is not the same as a parent/child relationship. Object 1 needs to be in the DB before you instert object 2 (to set the reference). You could always do a bulk insert of object 1, then have a trigger on object 1 insert that will insert object 2. Or you could loop twice, first inserting obj1 and then inserting obj2. I will modify my answer to reflect that. – mkorman Jan 27 '16 at 7:59
  • thank you for your answer and explanation that is what I really need. :) – Anjali Jan 27 '16 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.