function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
shan876shan876 

DML, 21.. my for loop please need assistance

Hi I have the following:
Code:
trigger updateCM on Account_Membership__c (after update) 
{
  // first, we need to change the status of all case roles if the
  // CM status value has changes
  
  if (Trigger.isUpdate) 
  {
    for (Integer i = 0; i < Trigger.new.size();i++)
    
    {
      Account_Membership__c casenew = Trigger.new[i];
      Account_Membership__c caseold = Trigger.old[i];
      
      // we check to see if the status has changed
      if (casenew.Status__c != caseold.Status__c) 
      {
            for(Contact_Membership__c cr: [select Id, Account_Membership__c  from Contact_Membership__c where Account_Membership__c = :casenew.id ])
            
            {
                cr.Status__c = casenew.Status__c;
                cr.Type__c =  casenew.Type__c;
                cr.Joined__c  = casenew.Joined__c;
                cr.Expires__c = casenew.Expires__c;
                cr.OwnerId =  casenew.OwnerId;
                update cr;
            } 
           
      }          
      }
    } 
  }
I keep geting
Too many DML statements: 21: Trigger.updateCM: line 25, column 17

What should I do...

 

modoleamodolea

Hi,

First, just some remarks:

Code:
trigger updateCM on Account_Membership__c (after update) // if you make AFTER, you cannot fired old values
{
  // first, we need to change the status of all case roles if the
  // CM status value has changes
  
  if (Trigger.isUpdate) // no need to do this when trigger fires update only
  {
    for (Integer i = 0; i < Trigger.new.size();i++)
    
    {
      Account_Membership__c casenew = Trigger.new[i];
      Account_Membership__c caseold = Trigger.old[i];
      
      // we check to see if the status has changed
      if (casenew.Status__c != caseold.Status__c) 
      {
            for(Contact_Membership__c cr: [select Id, Account_Membership__c  from Contact_Membership__c where Account_Membership__c = :casenew.id ])
            // try to not use query into the for loop
            {
                cr.Status__c = casenew.Status__c;
                cr.Type__c =  casenew.Type__c;
                cr.Joined__c  = casenew.Joined__c;
                cr.Expires__c = casenew.Expires__c;
                cr.OwnerId =  casenew.OwnerId;
                update cr; // try to not use dml call into the for loop
            } 
           
      }          
      }
    } 
  }

Then, try this:

Code:
trigger updateCM on Account_Membership__c (before update) 
{
    Map<Id, Account_Membership__c> amForQuery = new Map<Id, Account_Membership__c>();
    List<Contact_Membership__c> cmToUpdate = new List<Contact_Membership__c>();

    // get Account_Membership for who Status__c changed  
    for (Account_Membership__c amNew : Trigger.new)
    {
        if (amNew.Status__c != System.Trigger.oldMap.get(amNew.Id).Status__c)
        {
            amForQuery.put(amNew.Id, amNew);
        }
    }    

    // query Contact_Membership
    for(Contact_Membership__c cr : [SELECT Id, Account_Membership__c  
                                    FROM Contact_Membership__c 
                                    WHERE Account_Membership__c IN :amForQuery.KeySet() ])
    {
        cr.Status__c = amForQuery.get(cr.Account_Membership__c).Status__c;
        cr.Type__c =  amForQuery.get(cr.Account_Membership__c).Type__c;
        cr.Joined__c  = amForQuery.get(cr.Account_Membership__c).Joined__c;
        cr.Expires__c = amForQuery.get(cr.Account_Membership__c).Expires__c;
        cr.OwnerId =  amForQuery.get(cr.Account_Membership__c).OwnerId;
        cmToUpdate.add(cr);   
    }
    
    // DML statement
    if(cmToUpdate.size() > 0)
        update cmToUpdate;

}


Regards
adrian 

 

 



Message Edited by modolea on 08-08-2008 01:23 AM

Message Edited by modolea on 08-08-2008 01:42 AM
shan876shan876

Hi:

   First I like to thank you...

second I tried the re-written trigger which I like...

but I get a different error for DML rows 126???

Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger updateCM caused an unexpected exception, contact your administrator: updateCM: execution of BeforeUpdate caused by: System.Exception: Too many DML rows: 126: Trigger.updateCM: line 30, column 9

Line 30 is update cmToUpdate;...

Is there a way around this?

 

shan876shan876
Hi:
   So I took this trigger and limited to 100 and added a new field of datatype of a checkbox to update during this trigger...
Now how I do update the rest when the update__c field equals FALSE??? the rest of the records??
Code:
trigger updateCM on Account_Membership__c (before update) 
{
    Map<Id, Account_Membership__c> amForQuery = new Map<Id, Account_Membership__c>();
    List<Contact_Membership__c> cmToUpdate = new List<Contact_Membership__c>();

    // get Account_Membership for who Status__c changed  
    for (Account_Membership__c amNew : Trigger.new)
    {
        if (amNew.Status__c != System.Trigger.oldMap.get(amNew.Id).Status__c)
        {
            amForQuery.put(amNew.Id, amNew);
        }
    }    

    // query Contact_Membership
    for(Contact_Membership__c cr : [SELECT Id, Account_Membership__c  
                                    FROM Contact_Membership__c 
                                    WHERE Account_Membership__c IN :amForQuery.KeySet() LIMIT 100])
    {
        cr.Status__c = amForQuery.get(cr.Account_Membership__c).Status__c;
        cr.Type__c =  amForQuery.get(cr.Account_Membership__c).Type__c;
        cr.Joined__c  = amForQuery.get(cr.Account_Membership__c).Joined__c;
        cr.Expires__c = amForQuery.get(cr.Account_Membership__c).Expires__c;
        cr.OwnerId =  amForQuery.get(cr.Account_Membership__c).OwnerId;
        cr.updated__c = True;
        cmToUpdate.add(cr);   
    }

    // DML statement
    //if(cmToUpdate.size() > Limits.getLimitDMLRows())
    //System.Debug('You cannot perform a bulk update of more than ' + Limits.getLimitDMLRows() + ' Cases at a time.');
    if(cmToUpdate.size() > 0){
        update cmToUpdate;
        cmToUpdate.clear();
        }
        
    

    }

 
Thanks
modoleamodolea

Hi,

You don't have to LIMIT your query, Execution Governors and Limits allows you to retrive 1,000 records. See "Understanding Execution Governors and Limits" in Apex Language Reference.

Take a look on Apex Code samples, you'll find some efficient alternatives for avoiding runtime governor limits.
 

 Image:Icon doc sm.gif Avoiding runtime governor limits - alternative

 Image:Icon doc sm.gif Avoiding runtime governor limits - alternative 2

 Image:Icon doc sm.gif This is a helper class called by line 17 & 18

The idea is to use static class variables to store query results and process dml statements from two diferent triggers, one before update and other after update.

I hope this can help you.

regards
adrian

 



Message Edited by modolea on 08-08-2008 07:04 AM

Message Edited by modolea on 08-08-2008 07:05 AM

Message Edited by modolea on 08-08-2008 07:06 AM