In order to protect shared resources, Salesforce enforces a maximum number of DML statements which can be executed inside a single transaction. This is part of Governor limits. If a DML statement is nested
inside a loop’s body (For/While/Do-While) it might be executed more times than the Governor limit allows, making the code fail.
Thus it is a best practice to not have DML statements nested in the body of loops and instead perform the DML operation on a list of sObjects.
This rule raises an issue when it detects DML statements inside a loop.
Noncompliant code example
public class myDMLLoop {
public static void myFunction() {
for (Task task: [Select Id, subject from Task]) {
if (task.subject == 'foo') {
task.subject = 'bar';
update task; // Noncompliant
}
}
}
}
// Query in a while loop
public class myDMLLoop {
public static void myFunction(Task[] tasks) {
Integer i = 0;
while ( i < 1000) {
Task task = tasks[i];
if (task.subject == 'foo') {
task.subject = 'bar';
update task; // Noncompliant
}
}
}
}
// Query in a do-while loop
public class myDMLLoop {
public static void myFunction(Task[] tasks) {
Integer i = 0;
do {
Task task = tasks[i];
if (task.subject == 'foo') {
task.subject = 'bar';
update task; // Noncompliant
}
i++;
} while (i < 1000);
}
}
Compliant solution
public class myDMLLoop {
public static void myFunction() {
List<Task> updatedTasks = new List<Task>();
for (Task task: [Select Id, subject from Task]) {
if (task.subject == 'foo') {
task.subject = 'bar';
updatedTasks.add(task);
}
}
update updatedTasks;
}
}