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
john harvey 2john harvey 2 

How to update siblings records and parent record in a same trigger

Hi all,

I have written a code to update all the siblings records and parent records of the record getting updated. I want to use MAP in below trigger if it is possible. I want to optimize it using MAP. Can anyone please help me? Thank you so much.

 

trigger Addressflag on Address__c (After update, After Insert) {
    if(Trigger.isUpdate || Trigger.isInsert){
    List<ID> ConIds = new List<ID>();
    Boolean needsUpdate = FALSE; 
    for (Address__c Adds: trigger.new)
    {
    ConIds.add(Adds.contact__c);
    }
    system.debug('parent con ids'+ConIds);
    contact con = [select id, checkbox__c, recordTypeId from contact where Id IN :conIds];
    List<Address__c> otherAlt = new List<Address__c>([select id, contact__c, checkbox__c, contact__r.recordTypeId from Address__c where contact__c in: conIDs]);
        for (Address__c adds: trigger.new)
        {
            for (integer i=0; i < otherAlt.size(); i++)
            {
                if ((otherAlt[i].contact__c==adds.contact__c) && (otherAlt[i].id != adds.id))
                {
                     otherAlt[i].checkbox__c = FALSE;
                     con.checkbox__c=FALSE;
                     needsUpdate = TRUE;
                }
            }
        }

        if(checkrecursive.runOnce())
        {
              if (needsUpdate)
              {
                  update otherAlt;
                  update con;
              }
        }
    }
 }
Contact has master detail relationship with address. What I am trying to do is whenever the checkbox on any of the address is checked I am unchecking the same checkbox from all other siblings and parent record. I am acheving it through above trigger but I am concerned about the time when 1000s f records will get inserted at same time.
Best Answer chosen by john harvey 2
Prosenjit Sarkar 7Prosenjit Sarkar 7
Hi John,

I have observed your code. I just want to advise somthing,
  1. When you are listing some Ids please Set instead of List.
  2. Always use trigger handlers while writing triggers.(this is a best practice).
  3. In your code i don't think you need any Map or to write inner for loops.
I am attaching a sample code for your problem. let me know any problem you have found.

Trigger,
 
trigger AddressTrigger on Address__c (After update, After Insert) {
	if(Trigger.isUpdate || Trigger.isInsert){
		AddressTriggerHandler.flagAddresses(Trigger.New);
	}
}

Trigger Handler,
 
public class AddressTriggerHandler {
	public static void flagAddresses(List<Address__c> addressList) {
		Set<Id> contactIdSet = new Set<Id>();
		for(Address__c adrs : addressList) {
				if(adrs.checkbox__c)
					contactIdSet.add(adrs.Contact__c);
		}
		// Only Contacts that should be updated
		List<Contact> conList = [select id, checkbox__c, recordTypeId from contact where Id IN :contactIdSet];
		// Only Adresses that should be updated
		List<Address__c> otherAlt = [select id, contact__c, checkbox__c, contact__r.recordTypeId from Address__c where contact__c in: contactIdSet AND Id NOT IN :addressList];
		
		for(Contact con : conList)
			con.checkbox__c = FALSE;
		for(Address__c adrs : otherAlt)
			adrs.checkbox__c = FALSE;
		if(!conList.isEmpty())
			update conList;
		if(!otherAlt.isEmpty())
			update otherAlt;
	}
}

Please save the trigger handler first as an apex class. Then save your trigger. 

Thanks,
Prosenjit
 

All Answers

Prosenjit Sarkar 7Prosenjit Sarkar 7
Hi John,

I have observed your code. I just want to advise somthing,
  1. When you are listing some Ids please Set instead of List.
  2. Always use trigger handlers while writing triggers.(this is a best practice).
  3. In your code i don't think you need any Map or to write inner for loops.
I am attaching a sample code for your problem. let me know any problem you have found.

Trigger,
 
trigger AddressTrigger on Address__c (After update, After Insert) {
	if(Trigger.isUpdate || Trigger.isInsert){
		AddressTriggerHandler.flagAddresses(Trigger.New);
	}
}

Trigger Handler,
 
public class AddressTriggerHandler {
	public static void flagAddresses(List<Address__c> addressList) {
		Set<Id> contactIdSet = new Set<Id>();
		for(Address__c adrs : addressList) {
				if(adrs.checkbox__c)
					contactIdSet.add(adrs.Contact__c);
		}
		// Only Contacts that should be updated
		List<Contact> conList = [select id, checkbox__c, recordTypeId from contact where Id IN :contactIdSet];
		// Only Adresses that should be updated
		List<Address__c> otherAlt = [select id, contact__c, checkbox__c, contact__r.recordTypeId from Address__c where contact__c in: contactIdSet AND Id NOT IN :addressList];
		
		for(Contact con : conList)
			con.checkbox__c = FALSE;
		for(Address__c adrs : otherAlt)
			adrs.checkbox__c = FALSE;
		if(!conList.isEmpty())
			update conList;
		if(!otherAlt.isEmpty())
			update otherAlt;
	}
}

Please save the trigger handler first as an apex class. Then save your trigger. 

Thanks,
Prosenjit
 
This was selected as the best answer
RaidanRaidan
John, 

I believe the trigger above will break when you insert/update two addresses (checked) from two different contacts at the same time (say, use a test class or data loader to prove my point0.

To answer your question. If you are concerned about the data load, you can use a scheduled apex. The only problem is the changes will not happen right away. There are also some tricks to run the schedule from the trigger when the process is approaching its limit.
john harvey 2john harvey 2
thank you Ralden. I ll try prosenjit's code to resolve that.
Prosenjit Sarkar 7Prosenjit Sarkar 7
Hi John,
If your are satisfied with my answer, please make it as best answer :)

Thanks
Prosenjit