+ Start a Discussion
Blake TanonBlake Tanon 

Simple Trigger: Update child records.

I feel this would be an easy trigger to make, I'm not just a programmer of any sorts.  Here is what I need it to do:

When the parent record (contact) is updated or created, update all child records for partner_member__c.  There won't be anymore than 4 child records in the largest case.  

If anyone could help me with this I'd appreciate it!

Thanks,
Blake

Jerun JoseJerun Jose

trigger updateChild on Contact(after update){
    update [select id from partner_member__c where Contact__c in :trigger.new];
}

vijaymindvijaymind

Its could be that you upload Contact records from dataLoader so suppose you are goign to upload 50 contacts records then your partner_member__c records would be 50*4 approximately which is 200 .

Now if you makeing update statement inside the loop it will hit the limit .
So you have to change the approach .

here is the code would work fine !

 

Trigger updatepartnermember on Contact(after update,after insert ){

Map<Id,List<partner_member__c>> mapContactIdAndPartner = new Map<Id,List<partner_member__c>>();
for(partner_member__c obj :[select Id,Name from partner_member__c where Contact__c in : trigger.newmap.keyset()]){
if(mapContactIdAndPartner.get(obj.Contact__c) == null){
mapContactIdAndPartner.put(obj.Contact__c,new List<partner_member__c>());
}
mapContactIdAndPartner.get(obj.Contact__c).add(obj);
}

List<partner_member__c> lstToUpdate = new List<partner_member__c>();
for(Contact c : trigger.new){
List<partner_member__c> partner_member__lst = mapContactIdAndPartner.get(c.Id);
for(partner_member__c obj :partner_member__lst){
//your logic here
lstToUpdate.add(obj);
}
}

update lstToUpdate;
}

Jerun JoseJerun Jose
Don't want to criticize, but the requirements were pretty understated and I guess I made it as simple as possible.

P.S. There is no loop in the trigger I gave. Take a look. It has only 1 line.
Jerun JoseJerun Jose

Got bored, so thought I'd pick a fight.

 

Having a closer look at your code, I would like to recommend a few things.

 

Trigger updatepartnermember on Contact(after update,after insert ){
	Map<Id,List<partner_member__c>> mapContactIdAndPartner = new Map<Id,List<partner_member__c>>();
	// when you want ID of Sobjects you can just as well pass the SObject list.
	// so instead of giving Contact__c in : trigger.newmap.keyset() , you could as well just give Contact__c in : trigger.new, I prefer trigger.new - it looks better.
	for(partner_member__c obj :[select Id,Name from partner_member__c where Contact__c in : trigger.newmap.keyset()]){
		if(mapContactIdAndPartner.get(obj.Contact__c) == null){
			mapContactIdAndPartner.put(obj.Contact__c,new List<partner_member__c>());
		}
		mapContactIdAndPartner.get(obj.Contact__c).add(obj);
	}

	List<partner_member__c> lstToUpdate = new List<partner_member__c>();
	// why go for another loop here ??
	// what you are trying to do is to iterate throught he partner_member__c records, could have done it in the previous loop itself
	for(Contact c : trigger.new){
		List<partner_member__c> partner_member__lst = mapContactIdAndPartner.get(c.Id);
		// nested loops - bad for coding standards
		for(partner_member__c obj :partner_member__lst){
			//your logic here
			lstToUpdate.add(obj);
		}
	}

	// unguarded update
	update lstToUpdate;
}

A simplified version (??? not as simple as the first one) which lets you do some field mappings, (which is almost always the case) is given below

 

Trigger updatepartnermember on Contact(after update,after insert ){
	List<partner_member__c> lstToUpdate = new List<partner_member__c>();
	for(partner_member__c obj :[select fieldsNeeded from partner_member__c where Contact__c != null and Contact__c in : trigger.new]){
		obj.Field1__c = 'some value';
		lstToUpdate.add(obj);
	}

	if(!lstToUpdate.isEmpty())
		update lstToUpdate;

}

 

vijaymindvijaymind

I understand there is no for loop but trigger.new is a self list treated as loop.

Now suppose you are going to upload thoudsands of records then update statement will run the same number of records will hit the limit.

 

 

Jerun JoseJerun Jose

I'd have to disagree. Trigger.new is a list, but when you issue it in the where clause of a query, there will be one query issued which will use the ID values from trigger.new (as a collection). Also, even if you do a mass data load, Apex triggers are executed in batches of generally size 200. So even if you were doing thousands of updates, each trigger instance will be processing only 200 records at a time.

 

Apex triggers will process the entire volume of update in a single transaction. There will not be any splitting of volume of records. The volume split only happens with batch apex.

However, SFDC internally can manage performance by splitting the batch size of the trigger but that will be abstracted for the end user and apex developer

vijaymindvijaymind

Sorry My mistake . you are absolutely right this will invoke each time only once .

VirijaVirija
Thank You Jerun for the simplified code (Second part). Will there be any danger of hitting the limits, when we mass update parent or child records?

Regards,
Sravan.
Jerun JoseJerun Jose
Generally no. The trigger is more or less handled to operate for bulk operations. The one thing that you might want to consider is recursive calling.

Since the trigger also works for update, what sometimes happens is that your trigger tg1 updates the child object, the child object trigger tg2 updates the parent and this will fire tg1 again. So it ends up that the apex triggers are executed multiple times when you dont really need that.

There are many techniques to solve trigger recursion. Do a cursory search and come back if you have problems.