Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

I am trying to bulkify my trigger and looking for help looking for help. It works fine as it is for a single record but need to ensure it works in bulk, so need to bulkify it but not sure how.

Also, I will appreciate if some one can help me with test class as well.

Thanks RP

trigger updateSerialList on Meter_Serial_Info__c(Before insert, Before update, Before delete){

    if(Trigger.isDelete || Trigger.isUpdate)
    {
        for (Meter_Serial_Info__c msio: trigger.old)
        {
            if(msio.Serial__c<> Null)
            {
                List<Serial_List__c> scsi = [select Maker__c,  id ,Array__c from Serial_List__c where Serial__c = : msio.Serial__c];
                if(scsi.size()>0)
                {
                    scsi[0].Array__c= Null;
                    update scsi;                    
                }
            }
        }
    }


    if(Trigger.isInsert || Trigger.isUpdate)
    {
        for (Meter_Serial_Info__c msi: trigger.new)
        {
            if(msi.Serial__c<> Null)
            {
                List<Serial_List__c> scsi = [select Maker__c, Array__c, id from Serial_List__c where Serial__c = : msi.Serial__c];
                if(scsi.size()>0)
                {
                    scsi[0].Array__c= msi.Array__c;
                    update scsi;
                    msi.Maker__c = scsi[0].Maker__c;               
                }
                else
                {
                    msi.Maker__c = 'Not Available'; 
                }
            }
        }
    }
}
share|improve this question
6  
Google bulkifying apex trigger, there's lots out there...Google is your friend :) –  Phil Hawthorn Jun 24 at 16:28
2  
welcome RPham, it may be helpful if you try to specificly ask what part of bulkification, or applying it to your code is confusing you. Give it a try and share with us where you get stuck. –  Samuel De Rycke Jun 24 at 16:44
    
possible duplicate of General trigger bulkification - best practices –  Christian Deckert Aug 21 at 18:19

4 Answers 4

up vote 4 down vote accepted

Try this. As said above, the main points are to remove SOQL & DML statement from any loops.

trigger updateSerialList on Meter_Serial_Info__c(Before insert, Before update, Before delete) {

    if (Trigger.isDelete || Trigger.isUpdate) {

        Set<Id> serialIds = new Set<Id>();

        for (Meter_Serial_Info__c msio : Trigger.old) {

            if (msio.Serial__c != null) {

                serialIds.add(msio.Serial__c);
            }
        }

        List<Serial_List__c> serialListsToUpdate = new List<Serial_List__c>([]);

        for (Serial_List__c sl : [  SELECT
                                        Id,
                                        Array__c
                                    FROM
                                        Serial_List__c
                                    WHERE
                                        Serial__c IN : serialIds    ]) {

            sl.Array__c = null;

            serialListsToUpdate.add(sl);
        }

        if (!serialListsToUpdate.isEmpty()) {

            update serialListsToUpdate;
        }
    }

    if (Trigger.isInsert || Trigger.isUpdate) {

        Set<Id> serialIds = new Set<Id>();

        for (Meter_Serial_Info__c msio : Trigger.old) {

            if (msio.Serial__c != null) {

                serialIds.add(msio.Serial__c);
            }
        }

        List<Serial_List__c> relatedSerialListsToUpdate = new List<Serial_List__c>([
            SELECT
                Id,
                Array__c,
                Serial__c
            FROM
                Serial_List__c
            WHERE
                Serial__c IN : serialIds
        ]);

        List<Serial_List__c> serialListsToUpdate = new List<Serial_List__c>();

        for (Meter_Serial_Info__c msi : Trigger.new) {

            if (serialIds.contains(msi.Serial__c)) {

                for (Serial_List__c sl : relatedSerialListsToUpdate) {

                if (sl.Serial__c == msi.Serial__c) {

                    sl.Array__c = msi.Arry__c;
                    serialListsToUpdate.add(sl);

                    msi.Maker__c = sl.Maker__c;
                }
            }   

            } else {

                msi.Maker__c = 'Not Available';
            }
        }

        if (!serialListsToUpdate.isEmpty()) {

            update serialListsToUpdate;
        }
    }
}
share|improve this answer

The first key to Bulkification is removing SOQL and DML from loops (there are others, but this seems to be your biggest issue above). You need to leverage collections to help you do this. While I won't rewrite your trigger for you, I will give you some starting points.

In your trigger above you have a SOQL query for every record in trigger.new. So for every record that was updated, you run a SOQL query and possible do a DML statement. If you try to mass update/insert/delete some Meter_Serial_Info__c records, say a group of 200, then that means you will run 200 SOQL queries, and could possibly have 200 DML statements. The limit of SOQL queries in a single execution context is 100, so you have already doubled the limit with a relatively small mass DML.

Instead of querying for the specific Serial_List__c record in your loop. Query for all related Serial_List__c records outside of the loop and store it in a map so you can access it later.

map<Id,Serial_List__c> slMap = new map<Id,Serial_List__c>();
for(Meter_Serial_Info__c msi: trigger.new) {
    slMap.put(msi.Serial__c, null);
}
slMap.remove(null);
slMap.putAll([Select Id, Maker__c, Array__c 
               From Serial_List__c 
               Where Serial__c IN : slMap.keyset()]);

Now within your loop you can access the Serial List Object that is associated with your Meter_Serial_Info__c object.

for (Meter_Serial_Info__c msi: trigger.new) {
    if(msi.Serial__c != null) {
        slMap.get(msi.Serial__c).Array__c = msi.Array__c;
        msi.Maker__c = slMap.get(msi.Serial__c).Maker__c;               
    }
    else {
        msi.Maker__c = 'Not Available'; 
    }
}

Now notice the DML statement is no longer in the loop either. You now can call a single DML statement after all your changes have been made on your collections

for (Meter_Serial_Info__c msi: trigger.new) {
    if(msi.Serial__c != null) {
        slMap.get(msi.Serial__c).Array__c = msi.Array__c;
        msi.Maker__c = slMap.get(msi.Serial__c).Maker__c;               
    }
    else {
        msi.Maker__c = 'Not Available'; 
    }
}
***update slMap.values();***

For a update of 200 records, you would have been making 200 SOQL statements as well as possibly as many as 200 DML statements. Now you have 1 SOQL query, and 1 DML statement.

Also, check out the web, there are tons of resource son this. Here is an oldy but goody from Jeff Douglas.

http://blog.jeffdouglas.com/2009/04/20/writing-bulk-triggers-for-salesforce/

Hope that helps, and Good Luck.

share|improve this answer

Two important things to keep in mind for bulkifying code is to:

  • Avoid SOQL inside for loops Performing DML operations such
  • insert/updates on a List of objects instead of a single object inside a loop.

Move your SOQL statement outside the loop and store the data in a List/Map.

Also add the objects that need to be updated into a List and perform one update/insert/delete on this.

Please refer to this for easy to understand code examples. In any case, you need to know this to program in APEX. https://developer.salesforce.com/page/Apex_Code_Best_Practices

share|improve this answer

Since you are starting with Apex, it is best to start with the best practices when coding. One of them is to use Trigger framework so it is easy to plugin your custom logic inside a trigger. Examples of trigger frameworks are: https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices http://developer.force.com/cookbook/recipe/trigger-pattern-for-tidy-streamlined-bulkified-triggers ...

share|improve this answer
    
Dont know who to thank most as each one of you have went beyond to help me. It lets me pick only one as accepted answer otherwise I would pick all. I appreciate and thank each one of you for giving your input. –  RPham Jun 24 at 21:05
    
You can at least upvote all helpful answers :) –  Richard N Jun 25 at 18:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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