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
LaaralLaaral 

Custom Validation errors while saving record(s) on Delete - after deployment of APEX Trigger

Hi I get this error message while trying to delete a setup from main account which has multiple setups.  Main idea is that this would go through all the main account setups even when one of the setups is deleted. I would appreciate if you could give me some guidance.

 

trigger SetupChangeTechnologyListCheck on Setup__c (after insert, after update, after delete)
{
    for(Setup__c s : trigger.new)
    {
        
        Account acc = [SELECT Name, Service_Type_List__c FROM Account WHERE RecordType.Name = 'Main Account' AND Name = :s.Main_Account__c];
        UpdateMainAccountTechnologyList techList = new UpdateMainAccountTechnologyList();
        techList.UpdateList(acc);
        
    }
}

Best Answer chosen by Admin (Salesforce Developers) 
GlynAGlynA

After providing you with a quick answer, I realized that you are going to have other problems with your trigger as written.  Notably, you have a SOQL query inside the for loop.  This is not bulk-safe, as DML of 100+ records will cause you to hit the limit on SOQL queries.

 

I have refactored your trigger to eliminate this problem.  I hope this is helpful.

 

trigger SetupChangeTechnologyListCheck on Setup__c (after insert, after update, after delete)
{
    Id  rtid_Setup_Main_Account = [SELECT Id FROM RecordType WHERE DeveloperName = 'Main_Account'][0].Id;

    Set<String> set_MainAccountNames = new Set<String>();

    for ( Setup__c setup : trigger.isDelete ? trigger.old : trigger.new )
    {
        set_MainAccountNames.add( setup.Main_Account__c );
    }

    for ( Account theAccount :
        [   SELECT  Name, Service_Type_List__c
            FROM    Account
            WHERE   (   RecordTypeId = :rtid_Setup_Main_Account
                    AND Name IN :set_MainAccountNames
                    )
        ]
        )
    {
        (new UpdateMainAccountTechnologyList()).UpdateList( theAccount );
    }
}

 

If this helps, please mark it as a solution, and give kudos (click on the star) if you think I deserve them. Thanks!

 

-Glyn Anderson
Certified Salesforce Developer | Certified Salesforce Administrator

All Answers

Vinita_SFDCVinita_SFDC

Hello,

 

The context variable Trigger.new is only available in "after insert" and "after update" triggers. Check out the "Trigger context variables" section in the Apex Developer's Guide. You probably want to use System.Trigger.old for the "after delete".

GlynAGlynA

The easy way to fix this is to change your for loop to this:

 

    for ( Setup__c s : trigger.isDelete ? trigger.old : trigger.new )

If this helps, please mark it as a solution, and give kudos (click on the star) if you think I deserve them. Thanks!

 

-Glyn Anderson
Certified Salesforce Developer | Certified Salesforce Administrator

GlynAGlynA

After providing you with a quick answer, I realized that you are going to have other problems with your trigger as written.  Notably, you have a SOQL query inside the for loop.  This is not bulk-safe, as DML of 100+ records will cause you to hit the limit on SOQL queries.

 

I have refactored your trigger to eliminate this problem.  I hope this is helpful.

 

trigger SetupChangeTechnologyListCheck on Setup__c (after insert, after update, after delete)
{
    Id  rtid_Setup_Main_Account = [SELECT Id FROM RecordType WHERE DeveloperName = 'Main_Account'][0].Id;

    Set<String> set_MainAccountNames = new Set<String>();

    for ( Setup__c setup : trigger.isDelete ? trigger.old : trigger.new )
    {
        set_MainAccountNames.add( setup.Main_Account__c );
    }

    for ( Account theAccount :
        [   SELECT  Name, Service_Type_List__c
            FROM    Account
            WHERE   (   RecordTypeId = :rtid_Setup_Main_Account
                    AND Name IN :set_MainAccountNames
                    )
        ]
        )
    {
        (new UpdateMainAccountTechnologyList()).UpdateList( theAccount );
    }
}

 

If this helps, please mark it as a solution, and give kudos (click on the star) if you think I deserve them. Thanks!

 

-Glyn Anderson
Certified Salesforce Developer | Certified Salesforce Administrator

This was selected as the best answer
GlynAGlynA

BTW:  If you make the method 'UpdateList' a static method, then you can call it without the constructor call:

 

    UpdateMainAccountTechnologyList.UpdateList( theAccount );

-Glyn

GlynAGlynA

Is Main_Account__c really a String field?  Or is it a Lookup field?

 

-Glyn

GlynAGlynA

If Main_Account__c is actually a Lookup field (and if UpdateList becomes a static method), then the code becomes this:

 

trigger SetupChangeTechnologyListCheck on Setup__c (after insert, after update, after delete)
{
    Id  rtid_Setup_Main_Account = [SELECT Id FROM RecordType WHERE DeveloperName = 'Main_Account'][0].Id;

    Set<Id> set_MainAccountIDs = new Set<Id>();

    for ( Setup__c setup : trigger.isDelete ? trigger.old : trigger.new )
    {
        set_MainAccountIDs.add( setup.Main_Account__c );
    }

    for ( Account theAccount :
        [   SELECT  Id, Name, Service_Type_List__c
            FROM    Account
            WHERE   (   RecordTypeId = :rtid_Setup_Main_Account
                    AND Id IN :set_MainAccountIDs
                    )
        ]
        )
    {
        UpdateMainAccountTechnologyList.UpdateList( theAccount );
    }
}

-Glyn

LaaralLaaral
Many thanks Main_Account__c is a string so the solution I marked worked! :)