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
greg521greg521 

Simple Trigger Not Working

Hi, 

I'm fairly new to Apex and I have a trigger that isn't working.

Basically, I have two objects of importance - a holder and a provider. The holder has a name field that I want to be automatically set to the name of the provider. so far I have:

 

trigger rename on Holder__c (before update, before insert) {
    for(Holder__c h : trigger.new){
           h.Name = h.Provider__c.Name;
     }
}

 

but i'm getting a weird error. any help would be greatly appreciated.

-greg

Best Answer chosen by Admin (Salesforce Developers) 
Alex.AcostaAlex.Acosta

There can be two reasons for this,

1) You're dealing with a Master-Detail Relationship. On the detail records, name is no longer required as it's just the record Id.

2) If this is not a master detail relationship, and this is just a standard lookup, you'll need to query your parent objects first so you have access to those records. On the trigger itself you only have access to the root record. Anything else you'll have to query for as in the example provided above...

 

Here's sudo code i wrote out quickly....

trigger rename on Holder__c (before update, before insert) {
	Map<Id, Provider__c> providerMap = new Map<Id, Provider__c>();
	Set<Id> providerIds = new Set<Id>();
	
	for(Holder__c h :trigger.new){
		if(null != h.Provider__c && '' != h.Provider__c)
			providerIds.add(h.Provider__c);
	}
	
	// if this does not work try the next one
	providerMap = [SELECT Id, Name FROM Provider__c WHERE Id IN :providerIds];
	// if above does not work try this one
	for(Provider__c p :[SELECT Id, Name FROM Provider__c WHERE Id IN :providerIds]){
		providerMap.put(p.Id, p);
	}
	
    for(Holder__c h : trigger.new){
			if(null != h.Provider__c && '' != h.Provider__c && providerMap.containsKey(h.Provider__c))
				h.Name = providerMap.get(h.Provider__c).Name;
    }
}

 

All Answers

Saikishore Reddy AengareddySaikishore Reddy Aengareddy

is provider__c an object or a field on Holder__c object? If object what is the relationship between holder and provider? Post your error message 

greg521greg521

Sorry for the confusion - Provider is both the name of an object and the name of the field within Holder. 

 

The error message is:

 

Error: Compile Error: Invalid foreign key relationship: Holder__c.Provider__c at line 3 column 35

vishal@forcevishal@force

Hi,

 

The issue here is because when you are referring the Provider Object from the Holder Object, you've used h.Provider__c.Name. This is incorrect. For fields on a reference object, you have to traverse using __r

 

It should be h.Provider__r.Name;

 

 

trigger rename on Holder__c (before update, before insert) {
    for(Holder__c h : trigger.new){
           h.Name = h.Provider__r.Name;
     }
}

Rahul SharmaRahul Sharma

Hello greg521,

 

Only Parent object's Id is retrieved with Trigger.new, For fetching other field values, you might need a query.

Try below example:

 

trigger copyPhone on Contact (before update, before insert) {    
    Set<Id> setAccountId = new Set<Id>();
       //Fetch all Account Ids
    for(Contact c : Trigger.new){
        setAccountId.add(c.AccountId);
    }
    
    //Prepare Account Map 
    Map<Id, String> mapAccount = new Map<Id, String>();
    for(Account a : [Select Phone, Name from Account where Id IN: setAccountId]){
        mapAccount.put(a.Id, a.Phone);
    }

    
    //Update the Contact field from parent field
    for(Contact c : Trigger.new){
        if(mapAccount.containsKey(c.AccountId)){
            c.Phone = mapAccount.get(c.AccountId);
        }
     }
}

 

greg521greg521

When I use __r instead my Holder object is automatically generated names like a0TE0000001bU0q.

Any ideas on why that may be?

Alex.AcostaAlex.Acosta

There can be two reasons for this,

1) You're dealing with a Master-Detail Relationship. On the detail records, name is no longer required as it's just the record Id.

2) If this is not a master detail relationship, and this is just a standard lookup, you'll need to query your parent objects first so you have access to those records. On the trigger itself you only have access to the root record. Anything else you'll have to query for as in the example provided above...

 

Here's sudo code i wrote out quickly....

trigger rename on Holder__c (before update, before insert) {
	Map<Id, Provider__c> providerMap = new Map<Id, Provider__c>();
	Set<Id> providerIds = new Set<Id>();
	
	for(Holder__c h :trigger.new){
		if(null != h.Provider__c && '' != h.Provider__c)
			providerIds.add(h.Provider__c);
	}
	
	// if this does not work try the next one
	providerMap = [SELECT Id, Name FROM Provider__c WHERE Id IN :providerIds];
	// if above does not work try this one
	for(Provider__c p :[SELECT Id, Name FROM Provider__c WHERE Id IN :providerIds]){
		providerMap.put(p.Id, p);
	}
	
    for(Holder__c h : trigger.new){
			if(null != h.Provider__c && '' != h.Provider__c && providerMap.containsKey(h.Provider__c))
				h.Name = providerMap.get(h.Provider__c).Name;
    }
}

 

This was selected as the best answer
greg521greg521

The second option seemed to do the trick. Thanks.