[SalesForce] How to solve Self Reference from Trigger -Recursive Trigger

I have written a test class to delete the related list records and update master detail Object fields value when the Master detail two fields(Model&Version) changes.But getting error

Trigger:

trigger ModelVersionChange on Opportunity_car_set__c (before update) {
    List<Service__c> newService = [select id from Service__c where Opportunity_car_set__c in:trigger.newmap.keyset()];
    List<Accompaniment__c> newAccompaniment = [select id from Accompaniment__c where Opportunity_car_set__c in:trigger.newmap.keyset()];
    Map<Id,Opportunity_car_set__c> mOldValue = new Map<Id,Opportunity_car_set__c>();
    mOldValue = trigger.oldMap;
    for(Opportunity_car_set__c newcont: trigger.new) {
        if((newcont.Model__c != mOldValue.get(newcont.Id).Model__c)||(newcont.Version__c != mOldValue.get(newcont.Id).Version__c)) {
            newcont.Price_HT__c = null;
            newcont.TVN_Amount__c = null;
            delete newService;
            delete newAccompaniment;
        }
    }
 }

Error:Apex trigger ModelVersionChange caused an unexpected
exception, contact your administrator: Rfleet_ModelVersionChange:
execution of BeforeUpdate caused by: System.DmlException: Delete
failed. First exception on row 0 with id a0F4E000000CsrHUAS; first
error: SELF_REFERENCE_FROM_TRIGGER, Object (id = a0C4E000000mIrk) is
currently in trigger Rfleet_ModelVersionChange, therefore it cannot
recursively update itself: []: Trigger.Rfleet_ModelVersionChange: line
11, column 1

Best Answer

The recursion problem is likely to be the result of the combination of this trigger and another trigger. (Your updated question now shows that and someone can answer about that.)

But the trigger you have posted has the problem that it deletes the Service__c and Accompaniment__c objects for all the Opportunity_car_set__c objects that the trigger is firing for and so is logically wrong for the bulk case (where there are multiple Opportunity_car_set__c objects). Doing the deletes inside the loop will also hit governor limits in the bulk case.

This approach (making use of relationship queries) ensures that it is the related Service__c and Accompaniment__c objects that are deleted:

trigger ModelVersionChange on Opportunity_car_set__c (before update) {
    Service__c[] serviceDeletes = new Service__c[] {};
    Accompaniment__c[] accompanimentDeletes = new Accompaniment__c[] {};
    for (Opportunity_car_set__c ocs : [
            select Model__c, Version__c,
                    (select Id from Services__r),
                    (select Id from Accompaniments__r)
            from Opportunity_car_set__c
            where Id in :Trigger.newMap.keySet()
            ]) {
        Opportunity_car_set__c old = Trigger.oldMap.get(ocs.Id);
        if (ocs.Model__c != old.Model__c || ocs.Version__c != old.Version__c) {
            ocs.Price_HT__c = null;
            ocs.TVN_Amount__c = null;
            serviceDeletes.addAll(ocs.Services__r);
            accompanimentDeletes.addAll(ocs.Accompaniments__r);
        }
    }
    delete serviceDeletes;
    delete accompanimentDeletes;
}
Related Topic