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
Alessandro PatricelliAlessandro Patricelli 

Better way to write this code ?

Hi everyone.
I just wrote this trigger that helps me to update some fields based on records of my custom metadata types.

My friend is telling me that my code would hit SOQL Query limits... so it's bad and i must try to find a new way to write this code.
I just checked on help.salesforce.com 
--> https://help.salesforce.com/articleView?id=custommetadatatypes_limits.htm&type=5

and it says : 
SOQL queries per Apex transaction Unlimited

This is my code:
trigger ProfitOfferInsert on Quote (before update, before insert) 
{
	EX__mdt[] metaList = [SELECT Business_Unit__c, OfferType__c, ProfitCenter__c, Soluzione__c, Tipo__c FROM EX__mdt];

	for(Quote q : Trigger.new) 
	{	
		for(EX__mdt e : metaList)
		{
			if(q.Business_Unit__c == e.Business_Unit__c && q.Tipo__c == e.Tipo__c && q.Soluzione__c == e.Soluzione__c) 
			{
				q.Profit_Center__c = e.ProfitCenter__c;
                q.OfferType__c = e.ProfitCenter__c;
			}
		}
	}
    
}

So, what do you think guys ? Will this code Hit SOQL Query Limits or not?

P.S: Inside my custom metadata type we have only 25 records but maybe in future this number will increase.
Thanks in advance
Best Answer chosen by Alessandro Patricelli
Ajay K DubediAjay K Dubedi
Hi Alessandro,

* Please use below code it is as per best practices:

Trigger--->
trigger ProfitOfferInsert on Quote (before update, before insert) 
{
    if (Trigger.isBefore)
    {
    set<id> Business_Unit_set = set<id>();
    set<id> Soluzione_set = set<id>();
    set<id> Tipo_set = set<id>();
    for(Quote q : Trigger.new) 
    {
        Business_Unit_set.add(q.Business_Unit__c);
        Soluzione_set.add(q.Soluzione__c);
        Tipo_set.add(q.Tipo__c);
    }
    List<EX__mdt> metaList = [SELECT Business_Unit__c, OfferType__c, ProfitCenter__c, Soluzione__c, Tipo__c FROM EX__mdt where Business_Unit__c in: Business_Unit_set and Tipo__c in: Tipo_set and Soluzione__c in: Tipo_set]
    for(Quote q : Trigger.new)
    {
        for(EX__mdt ex_md :  metaList)
        {
            ex_md.Profit_Center__c = e.ProfitCenter__c;
            ex_md.OfferType__c = e.ProfitCenter__c;
             
        }
    }
    }
}


I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.

Thanks and Regards,
Ajay Dubedi
www.ajaydubedi.com

All Answers

karthikeyan perumalkarthikeyan perumal
Hello, 

your code will not hit governer limits, coz u r using SOQL out side of the loop. and try use trigger context variable to make sure this trigger excutes in proper events. 

sample code: 
 
trigger ProfitOfferInsert on Quote (before update, before insert) 
{
	EX__mdt[] metaList = [SELECT Business_Unit__c, OfferType__c, ProfitCenter__c, Soluzione__c, Tipo__c FROM EX__mdt];
    if (Trigger.isBefore){
	for(Quote q : Trigger.new) 
	{	
		for(EX__mdt e : metaList)
		{
			if(q.Business_Unit__c == e.Business_Unit__c && q.Tipo__c == e.Tipo__c && q.Soluzione__c == e.Soluzione__c) 
			{
				q.Profit_Center__c = e.ProfitCenter__c;
                q.OfferType__c = e.ProfitCenter__c;
			}
		}
	}
	}
    
}


hope this helps.

thanks
karthik

 
Alessandro PatricelliAlessandro Patricelli
Thank you so much!
I had the same thought about that SOQL Query becuase its outside the for loop.

What about the two nested loop ? Is it ok or it wil have some kind of limitations ? 
For example: if I have 100k records inside EX_mdt that for loop will run for 100k records, is that a problem ?
karthikeyan perumalkarthikeyan perumal
Hello, 

nested loop that not an issue.  100K chance are there for  heap size is exceeded error. 

tyr use below query and let me know its works or not? 
 
trigger ProfitOfferInsert on Quote (before update, before insert) 
{
	
    if (Trigger.isBefore){
	for(Quote q : Trigger.new) 
	{	
		for( List<EX__mdt> metaList = [SELECT Business_Unit__c, OfferType__c, ProfitCenter__c, Soluzione__c, Tipo__c FROM EX__mdt where Business_Unit__c=q.Business_Unit__c and Tipo__c=q.Tipo__c and Soluzione__cq.Soluzione__c ])
		{
			 
				metaList.Profit_Center__c = e.ProfitCenter__c;
                metaList.OfferType__c = e.ProfitCenter__c;
			 
		}
	}
	}
    
}

hope this helps. 

Thanks
karthik

 
Alessandro PatricelliAlessandro Patricelli
I just tried the modified code you wrote but it doesnt work...
User-added image
I tried the query as well it doesnt work

Thanks for you reply and your help...
Alessandro PatricelliAlessandro Patricelli
User-added image
I dont know if it can be usefull or not, but i was going to change my code like that... just to take one record from my metaList... what do you think ?
karthikeyan perumalkarthikeyan perumal
sorry its my mistake.. 
try below code
trigger ProfitOfferInsert on Quote (before update, before insert) 
{
	
    if (Trigger.isBefore){
	for(Quote q : Trigger.new) 
	{	
		for( EX__mdt metaList : [SELECT Business_Unit__c, OfferType__c, ProfitCenter__c, Soluzione__c, Tipo__c FROM EX__mdt where Business_Unit__c =: q.Business_Unit__c and Tipo__c =: q.Tipo__c and Soluzione__c =: q.Soluzione__c ])
		{
			 
				metaList.Profit_Center__c = e.ProfitCenter__c;
                metaList.OfferType__c = e.ProfitCenter__c;
			 
		}
	}
	}
    
}

hope this will work for you.  

Thanks
karthik
 
Alessandro PatricelliAlessandro Patricelli
Hi thanks for you answer.

Can i ask few questions ?
1- Why are you trying to put the SOQL query inside the for loop and not anymore outside?
2- line 10-11, why you update metalist? e variable doesnt exist.. i should update Quote q not e or metaList

I tried your code doesnt work because e variable doesnt exist.

Thanks for your answer
Ajay K DubediAjay K Dubedi
Hi Alessandro,

* Please use below code it is as per best practices:

Trigger--->
trigger ProfitOfferInsert on Quote (before update, before insert) 
{
    if (Trigger.isBefore)
    {
    set<id> Business_Unit_set = set<id>();
    set<id> Soluzione_set = set<id>();
    set<id> Tipo_set = set<id>();
    for(Quote q : Trigger.new) 
    {
        Business_Unit_set.add(q.Business_Unit__c);
        Soluzione_set.add(q.Soluzione__c);
        Tipo_set.add(q.Tipo__c);
    }
    List<EX__mdt> metaList = [SELECT Business_Unit__c, OfferType__c, ProfitCenter__c, Soluzione__c, Tipo__c FROM EX__mdt where Business_Unit__c in: Business_Unit_set and Tipo__c in: Tipo_set and Soluzione__c in: Tipo_set]
    for(Quote q : Trigger.new)
    {
        for(EX__mdt ex_md :  metaList)
        {
            ex_md.Profit_Center__c = e.ProfitCenter__c;
            ex_md.OfferType__c = e.ProfitCenter__c;
             
        }
    }
    }
}


I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.

Thanks and Regards,
Ajay Dubedi
www.ajaydubedi.com
This was selected as the best answer
Alessandro PatricelliAlessandro Patricelli
Hi Ajay Dubedi, 
thx for you answer but I must update Quote Q not another EX_md (line 17-21).
Thanks anywayUser-added image
karthikeyan perumalkarthikeyan perumal
trigger ProfitOfferInsert on Quote (before update, before insert) 
{
    if (Trigger.isBefore)
    {
    set<id> Business_Unit_set = set<id>();
    set<id> Soluzione_set = set<id>();
    set<id> Tipo_set = set<id>();
    for(Quote q : Trigger.new) 
    {
        Business_Unit_set.add(q.Business_Unit__c);
        Soluzione_set.add(q.Soluzione__c);
        Tipo_set.add(q.Tipo__c);
    }
    List<EX__mdt> metaList = [SELECT Business_Unit__c, OfferType__c, ProfitCenter__c, Soluzione__c, Tipo__c FROM EX__mdt where Business_Unit__c in: Business_Unit_set and Tipo__c in: Tipo_set and Soluzione__c in: Tipo_set]
    for(Quote q : Trigger.new)
    {
        for(EX__mdt ex_md :  metaList)
        {
            q.Profit_Center__c = ex_md.ProfitCenter__c;
            q.OfferType__c = ex_md.ProfitCenter__c;
             
        }
    }
    }
}

try this

 
Alessandro PatricelliAlessandro Patricelli
@karthikeyan 
Doesnt work, variable Set id doesnt exist
User-added image
Alessandro PatricelliAlessandro Patricelli
ok i fixed 
set<String> Business_Unit_set = new set<String>();
    set<String> Soluzione_set = new set<String>();
    set<String> Tipo_set = new set<String>();

now i got error on line 15 missing ; at for 
Alessandro PatricelliAlessandro Patricelli
Ok fixed, was missing ; at line 14! Thx both!!
karthikeyan perumalkarthikeyan perumal
try this 
 
trigger ProfitOfferInsert on Quote (before update, before insert) 
{
    if (Trigger.isBefore)
    {
    set<id> Business_Unit_set = new  set<id>();
    set<id> Soluzione_set =new set<id>();
    set<id> Tipo_set = new set<id>();
    for(Quote q : Trigger.new) 
    {
        Business_Unit_set.add(q.Business_Unit__c);
        Soluzione_set.add(q.Soluzione__c);
        Tipo_set.add(q.Tipo__c);
    }
    List<EX__mdt> metaList = [SELECT Business_Unit__c, OfferType__c, ProfitCenter__c, Soluzione__c, Tipo__c FROM EX__mdt where Business_Unit__c in: Business_Unit_set and Tipo__c in: Tipo_set and Soluzione__c in: Tipo_set];
    for(Quote q : Trigger.new)
    {
        for(EX__mdt ex_md :  metaList)
        {
            q.Profit_Center__c = ex_md.ProfitCenter__c;
            q.OfferType__c = ex_md.ProfitCenter__c;
             
        }
    }
    }
}

put semi colon for list ending stmt.
 
Deepali KulshresthaDeepali Kulshrestha
Hi Alessandro,

I have through your question. The code will not hit the governor limit but this is not the best way to write the trigger.
The best practices to write the trigger is:--  
trigger ProfitOfferInsert on Quote (before update, before insert) 
{
    if((trigger.isInsert || trigger.isupdate) && trigger.isbefore){
        ProfitOfferInsert_handler.ProfitOfferInsertmethod(trigger.new);
    }
}
public class ProfitOfferInsert_handler{
    public static void ProfitOfferInsertmethod(List<Quote> quoteList){
        try{
        EX__mdt[] metaList = [SELECT Business_Unit__c,                         OfferType__c, ProfitCenter__c, Soluzione__c, Tipo__c FROM EX__mdt];

            for(Quote q : quoteList) 
            {    
                    for(EX__mdt e : metaList)
                    {
                        if(q.Business_Unit__c == e.Business_Unit__c &&                 q.Tipo__c == e.Tipo__c 
&& q.Soluzione__c == e.Soluzione__c) 
                        {
                                q.Profit_Center__c = e.ProfitCenter__c;
                            q.OfferType__c = e.ProfitCenter__c;
                        }
                }
              }
        }
        catch(Exception e){
            System.debug('Error----->'+e.getMessage()+'Line No:--->'+getLineNumber());
        }
    }
}


To know more about governor limit please visit the link for reference:-
https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_apexgov.htm
I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.

Thanks and Regards,
Deepali Kulshrestha
www.kdeepali.com
 
Alex RanaAlex Rana
Is it help me somehow in my Florida Business for Sale (https://trufortebusinessgroup.com/)