0

From some research, I've seen many previous examples having the update inside a for loop which would reach over 150 DML statements if there were. I'm wondering why I still get the issue that there are too many DML statements. I update it outside the for loop so that should only be 1 DML statement. Is there any other way to make the for loop?

        List<Opportunity> opportunities = [Select id, amount, btcAmount__c from Opportunity];
        for(Opportunity opp: opportunities){
            if(opp.Amount != null) {
                opp.btcAmount__c = 200;
            }
            else {
                opp.btcAmount__c = null;
            }
        }
        try {
            update(opportunities);
        }
        catch (exception ex){
            system.debug(ex.getMessage());
        }
1
  • 2
    Are you using the (cacheable=true) parameter?
    – TSmith
    Jan 20, 2021 at 9:50

2 Answers 2

3

There are two main reasons why you'd get this error.

In Lightning (Aura and LWC), this error happens when you use @AuraEnabled(cacheable=true). This is because the result is cached, so if you include DML, those operations may not be carried out in subsequent method calls, leading to situations where the user thinks they've saved their data, but the server never actually got the data. Use cacheable=false if you include any DML in such a method.


In Visualforce, you cannot perform DML in a getter or constructor. This means the following are not allowed:

public class MyClass {
  Account accountRecord = new Account(Name='Demo');
  public MyClass() { // Constructor
    insert accountRecord; // illegal operation
  }
  public String getValue() { // Getter method
    insert accountRecord; // illegal operation
  }
  public String value2 {
    get { // Inline getter
      insert accountRecord; // illegal operation
    }
    set;
  }
}

This is because these methods are to be used only for initialization and calculating values to get (e.g. lazy loading data). These methods must be idempotent, meaning calling those methods more than once must result in the same behavior each time, and a DML operation breaks that assumption.

1

I suspect you might be using @AuraEnabled(cacheable=true) in your apex method. There is nothing to cache here. Just remove (cacheable=true) from annotation in your apex method.

Checkout similar problems questions here:-

  1. Storable Action - System.LimitException: Too many DML statements: 1
  2. LWC LimitException: Too many DML statements: 1

To understand when to use it and when not, You can see below example from docs, getOpptyOverAmount does not have dml operation and return list of records whereas updateOpptyStage has dml operation and annotated with just @AuraEnabled instead of @AuraEnabled(cacheable=true)

public with sharing class OpptiesOverAmountApex {
    @AuraEnabled(cacheable=true)
    public static List<Opportunity> getOpptyOverAmount(Decimal amount) {
        return [SELECT Id, Name, Amount, StageName, CloseDate FROM Opportunity WHERE Amount > :amount];
    }

    @AuraEnabled
    public static void updateOpptyStage(Decimal amount, String stage) {
        for (List<Opportunity> oppts:
            [SELECT Id, Name, Amount, StageName, CloseDate FROM Opportunity WHERE Amount > :amount]) {
                for(Opportunity o : oppts) {
                    o.StageName = stage;
                }
                update oppts;
            }
            return;
    }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .