+ Start a Discussion
Spencer EdieSpencer Edie 

LWC LimitException: Too many DML statements: 1

Hello all,
I'm getting the error in subject when I try to run this code:
@auraEnabled(cacheable=true)
public static void Equalize(string campaignsStr){
    string[] campaigns = (string[])JSON.deserialize(campaignsStr, list<String>.class);

    //Will hold the opportunities to update
    list<opportunity> updates = new list<opportunity>();

    //Will keep track of user ids and opp counts
    map<string, integer> owners = new map<string, integer>();	//String = OwnerID	Integer = opp count

    list<opportunity> opps = [SELECT Id, OwnerId FROM Opportunity WHERE Primary_Campaign_Filter__c IN :campaigns LIMIT 9999];
    System.debug('opps size: ' + opps.size());

    //Initializing the values of the owners map
    for(opportunity o: opps){
        if(owners.containsKey(o.ownerID)){
            owners.put(o.ownerID, owners.get(o.ownerID) + 1);
        }
        else{
            owners.put(o.ownerID, 1);
            System.debug('Adding owner ' + o.ownerId);
        }
    }

    //For each opportunity, if that owner already has more than the average,
    //give it to the person with the lowest opportunity count.
    integer threshold = opps.size()/owners.size() + 2;
    for(opportunity o: opps){
        if(owners.get(o.OwnerID) > threshold){
            string lowest = GetLowest(owners);
            owners.put(o.OwnerID, owners.get(o.OwnerID) - 1);
            owners.put(lowest, owners.get(lowest) + 1);
            o.OwnerID = lowest;
            updates.add(o);
        }
    }

    //PULL MY DEVIL TRIGGER
    System.debug('updates size: ' + updates.size());
    try{update updates;}
    catch(exception e){
        System.debug('exception: ' + e);
    }
}
I have seen solutions for Lightning Components (like https://developer.salesforce.com/forums/?id=906F0000000917DIAQ), but none that apply to Lightning Web Components. This is part of a component that has multiple other apex methods being called, and they all update fine.

Can anyone help me identify where the problem is?

Thanks!
 
Best Answer chosen by Spencer Edie
Spencer EdieSpencer Edie
SOLVED: Remove (Cacheable=true). Don't know why that fixed it, but here it is for anyone else who runs into this.

All Answers

Spencer EdieSpencer Edie
Notes from some debugging: running the same code as activated by a button in another sub-component produces the same error, but running the code in an anonymous window does not produce an error.
Spencer EdieSpencer Edie
SOLVED: Remove (Cacheable=true). Don't know why that fixed it, but here it is for anyone else who runs into this.
This was selected as the best answer
William Woodson 3William Woodson 3
My guess is that removing the Cacheable=true fixes it because the menthod returns void so there is nothing to cache.

 
Scott McClungScott McClung
It's because the equalize() method has a DML operation in it.

From the documentation: https://developer.salesforce.com/docs/component-library/documentation/lwc/apex
To improve runtime performance, annotate the Apex method with @AuraEnabled(cacheable=true), which caches the method results on the client. To set cacheable=true, a method must only get data, it can’t mutate (change) data.
To call an Apex method imperatively, you can choose to set cacheable=true. This setting caches the result on the client, and prevents Data Manipulation Language (DML) operations.
Karthickeyan B 2Karthickeyan B 2
If I remove cacheable=true then I am getting this Error. Let me know If someone can able to solve this.
.User-added image
Karthickeyan B 2Karthickeyan B 2
If you are using LWC for DML operation, Then Don't use the Wire. call Directly as I showed in the following Example. Here Next3 is the method that performs The DML operation. And Make sure that method Should Not contain  (Cacheable=true)
import { LightningElement,track,wire,api } from 'lwc';
import Next3 from '@salesforce/apex/RecordArchivePageCtrl.Next3';


export default class RecordArchivePage extends LightningElement {

    handleNext2(){
        this.progress = '4';
        this.firstPage = false;
        this.secondPage = false;
        this.thiredPage = false;
        this.fourthPage = true;
        Next3({selectedObject: this.selectedValue,sobjList:this.selectedRowUpdateList,recordMap:this.recordList}).then(result => {
            this.message = result;
            this.error = undefined;
            if(this.message !== undefined || this.message !== '' || result!==undefined || result !== '' ) {
                // eslint-disable-next-line no-alert
                alert("Workig "+result);
                
            }
        })
        .catch(error => {
            this.message = undefined;
            this.error = error;
            // eslint-disable-next-line no-console
            console.log("error s", JSON.stringify(this.error));
        });
        
    }
}

Wire method. call the directly the method
brahmaji tammanabrahmaji tammana
This (http://auraenabled.com/2020/04/can-we-perform-dml-using-wire-service/)blog post probably discussed in detail on this error.

http://auraenabled.com/2020/04/can-we-perform-dml-using-wire-service/

In short, we cannot perform dml from lwc when the apex method decorated with auraenabled(cacheable=true), but if this method call in other ways, it works normally. 
Varsha Dhage 11Varsha Dhage 11
Please make sure following things are in place: 
1) Remove (Cacheable=true) to get rid of exception
2) Make sure you are calling apex method imperatively instead of @wire, you can call it from connectedcallback() 
3) Add .then() and .catch() batch to cature returned result or error from apex method. 

import createRecord from '@salesforce/apex/BWITATActivity.createRecord;
export default class LWCComponent extends LightningElement {
connectedCallback() {
            createRecord({ area :this.selected_area})
                .then(result => {
                    console.log('created....',result);
                })
                .catch(error => {
                    console.log('Error: ', error);
                });
         }
}

Apex class method: 

   @AuraEnabled
        public static customObject__c createRecord(string area){
              customObject__c obj = new customObject__c();
             obj.area__c = area;
             insert obj;
             return obj;
     }
Please mark this answer as Best Answer if it helped you to resolve issue. 
Timo BierbrauerTimo Bierbrauer
Followed all the steps. Even tried to explicitly cacheable=false and I'm calling omperatively. Still get the same error. A difference to the scenario here is, that I'm doing a callout prior to DML.