Skip to content

Result

The DML library provides comprehensive result handling through the Result, OperationResult, RecordResult, and Error interfaces. These allow you to inspect the outcome of DML operations, including success/failure status, record IDs, and error details.

Overview

When you call commitWork() or dryRun(), a Result object is returned containing detailed information about each DML operation performed.

apex
DML.Result result = new DML()
    .toInsert(account)
    .toUpdate(contact)
    .commitWork();

// Check results by operation type
List<DML.OperationResult> insertResults = result.inserts();
List<DML.OperationResult> updateResults = result.updates();

// Check results by SObject type
DML.OperationResult accountInserts = result.insertsOf(Account.SObjectType);

Result Interface

The Result interface provides methods to access operation results.

Get All Results

Signature

apex
List<OperationResult> all();

Example

apex
DML.Result result = new DML()
    .toInsert(accounts)
    .toUpdate(contacts)
    .commitWork();

for (DML.OperationResult opResult : result.all()) {
    System.debug('Operation: ' + opResult.operationType());
    System.debug('Object: ' + opResult.objectType());
    System.debug('Has Failures: ' + opResult.hasFailures());
}

Get Results by Operation Type

Signatures

apex
List<OperationResult> inserts();
List<OperationResult> updates();
List<OperationResult> upserts();
List<OperationResult> deletes();
List<OperationResult> undeletes();
List<OperationResult> events();

Example

apex
DML.Result result = new DML()
    .toInsert(accounts)
    .toInsert(contacts)
    .commitWork();

// Get all insert results (one per SObject type)
List<DML.OperationResult> insertResults = result.inserts();

Assert.areEqual(2, insertResults.size()); // Account and Contact

Get Results by SObject Type

Signatures

apex
OperationResult insertsOf(Schema.SObjectType objectType);
OperationResult updatesOf(Schema.SObjectType objectType);
OperationResult upsertsOf(Schema.SObjectType objectType);
OperationResult deletesOf(Schema.SObjectType objectType);
OperationResult undeletesOf(Schema.SObjectType objectType);
OperationResult eventsOf(Schema.SObjectType objectType);

Example

apex
DML.Result result = new DML()
    .toInsert(accounts)
    .toInsert(contacts)
    .commitWork();

// Get insert results for Accounts only
DML.OperationResult accountResults = result.insertsOf(Account.SObjectType);
DML.OperationResult contactResults = result.insertsOf(Contact.SObjectType);

OperationResult Interface

The OperationResult interface provides detailed information about a specific DML operation.

Methods

Signatures

apex
OperationType operationType();      // DML operation type (INSERT_DML, UPDATE_DML, etc.)
Schema.SObjectType objectType();    // SObject type for this operation
Boolean hasFailures();              // True if any records failed
List<Error> errors();               // All errors from failed records
List<SObject> records();            // All records that were processed
List<SObject> successes();          // Records that succeeded
List<SObject> failures();           // Records that failed
List<RecordResult> recordResults(); // Individual record results

Example

apex
DML.Result result = new DML()
    .toInsert(accounts)
    .commitWork();

DML.OperationResult opResult = result.insertsOf(Account.SObjectType);

// Operation metadata
Assert.areEqual(DML.OperationType.INSERT_DML, opResult.operationType());
Assert.areEqual(Account.SObjectType, opResult.objectType());

// Check for failures
if (opResult.hasFailures()) {
    List<SObject> failedRecords = opResult.failures();
    List<DML.Error> allErrors = opResult.errors();
}

// Get successful records
List<SObject> successfulRecords = opResult.successes();

RecordResult Interface

The RecordResult interface provides information about individual record processing.

Methods

Signatures

apex
Id id();                  // Record ID (assigned after insert)
SObject record();         // The actual SObject record
Boolean isSuccess();      // True if this record succeeded
List<Error> errors();     // List of errors for this record

Example

apex
DML.Result result = new DML()
    .toInsert(accounts)
    .allowPartialSuccess()
    .commitWork();

DML.OperationResult opResult = result.insertsOf(Account.SObjectType);

for (DML.RecordResult recordResult : opResult.recordResults()) {
    if (recordResult.isSuccess()) {
        System.debug('Record inserted with Id: ' + recordResult.id());
        System.debug('Record: ' + recordResult.record());
    } else {
        System.debug('Record failed:');
        for (DML.Error error : recordResult.errors()) {
            System.debug('  - ' + error.message());
        }
    }
}

Error Interface

The Error interface provides details about DML errors.

Methods

Signatures

apex
String message();               // Error message
System.StatusCode statusCode(); // Status code (e.g., REQUIRED_FIELD_MISSING)
List<String> fields();          // Fields that caused the error

Example

apex
DML.Result result = new DML()
    .toInsert(accounts)
    .allowPartialSuccess()
    .commitWork();

for (DML.OperationResult opResult : result.all()) {
    for (DML.Error error : opResult.errors()) {
        System.debug('Error Message: ' + error.message());
        System.debug('Status Code: ' + error.statusCode());
        System.debug('Fields: ' + error.fields());
    }
}

OperationType Enum

The DML.OperationType enum identifies the type of DML operation.

Values

apex
DML.OperationType.INSERT_DML
DML.OperationType.UPDATE_DML
DML.OperationType.UPSERT_DML
DML.OperationType.DELETE_DML
DML.OperationType.UNDELETE_DML
DML.OperationType.PUBLISH_DML

Complete Examples

Basic Insert with Result

apex
Account account = new Account(Name = 'Test Account');

DML.Result result = new DML()
    .toInsert(account)
    .commitWork();

// Verify result
Assert.areEqual(1, result.inserts().size());

DML.OperationResult opResult = result.insertsOf(Account.SObjectType);
Assert.areEqual(1, opResult.records().size());
Assert.areEqual(1, opResult.successes().size());
Assert.areEqual(0, opResult.failures().size());
Assert.isFalse(opResult.hasFailures());
Assert.areEqual(DML.OperationType.INSERT_DML, opResult.operationType());
Assert.areEqual(Account.SObjectType, opResult.objectType());

// Check record result
DML.RecordResult recordResult = opResult.recordResults()[0];
Assert.isTrue(recordResult.isSuccess());
Assert.isNotNull(recordResult.id());
Assert.areEqual(account.Id, recordResult.id());

Partial Success Handling

apex
List<Account> accounts = new List<Account>{
    new Account(Name = 'Valid Account 1'),
    new Account(), // Missing required Name
    new Account(Name = 'Valid Account 2')
};

DML.Result result = new DML()
    .toInsert(accounts)
    .allowPartialSuccess()
    .commitWork();

DML.OperationResult opResult = result.insertsOf(Account.SObjectType);

// Check counts
Assert.areEqual(3, opResult.records().size());
Assert.areEqual(2, opResult.successes().size());
Assert.areEqual(1, opResult.failures().size());
Assert.isTrue(opResult.hasFailures());

// Process individual results
for (DML.RecordResult rr : opResult.recordResults()) {
    if (rr.isSuccess()) {
        System.debug('Record succeeded with Id: ' + rr.id());
    } else {
        System.debug('Record failed:');
        for (DML.Error error : rr.errors()) {
            System.debug('  Status: ' + error.statusCode());
            System.debug('  Message: ' + error.message());
            System.debug('  Fields: ' + error.fields());
        }
    }
}

Multiple Operation Types

apex
Account account = new Account(Name = 'New Account');
Contact existingContact = [SELECT Id, FirstName FROM Contact LIMIT 1];
existingContact.FirstName = 'Updated';
Lead leadToDelete = [SELECT Id FROM Lead LIMIT 1];

DML.Result result = new DML()
    .toInsert(account)
    .toUpdate(existingContact)
    .toDelete(leadToDelete)
    .commitWork();

// Check each operation type
Assert.areEqual(1, result.inserts().size());
Assert.areEqual(1, result.updates().size());
Assert.areEqual(1, result.deletes().size());

// Verify specific results
Assert.isFalse(result.insertsOf(Account.SObjectType).hasFailures());
Assert.isFalse(result.updatesOf(Contact.SObjectType).hasFailures());
Assert.isFalse(result.deletesOf(Lead.SObjectType).hasFailures());

Multiple SObject Types Same Operation

apex
Account account = new Account(Name = 'Test Account');
Contact contact = new Contact(FirstName = 'Test', LastName = 'Contact');
Lead lead = new Lead(FirstName = 'Test', LastName = 'Lead', Company = 'Test Co');

DML.Result result = new DML()
    .toInsert(account)
    .toInsert(contact)
    .toInsert(lead)
    .commitWork();

// Get all insert results (3 - one per SObject type)
List<DML.OperationResult> insertResults = result.inserts();
Assert.areEqual(3, insertResults.size());

// Get specific SObject type results
Assert.areEqual(1, result.insertsOf(Account.SObjectType).records().size());
Assert.areEqual(1, result.insertsOf(Contact.SObjectType).records().size());
Assert.areEqual(1, result.insertsOf(Lead.SObjectType).records().size());

Dry Run Results

apex
Account account = new Account(Name = 'Test Account');

DML.Result result = new DML()
    .toInsert(account)
    .dryRun();

// Result is returned but database is rolled back
Assert.areEqual(1, result.inserts().size());
Assert.isFalse(result.insertsOf(Account.SObjectType).hasFailures());

// No records in database
Assert.areEqual(0, [SELECT COUNT() FROM Account WHERE Name = 'Test Account']);

Accessing Records from Results

apex
List<Account> accounts = new List<Account>{
    new Account(Name = 'Account 1'),
    new Account(Name = 'Account 2'),
    new Account(Name = 'Account 3')
};

DML.Result result = new DML()
    .toInsert(accounts)
    .commitWork();

// Get the records that were processed
List<SObject> processedRecords = result.insertsOf(Account.SObjectType).records();

// They're the same references, so IDs are populated
Assert.areEqual(3, processedRecords.size());
for (SObject record : processedRecords) {
    Assert.isNotNull(record.Id);
}

// Get only successful records
List<SObject> successfulRecords = result.insertsOf(Account.SObjectType).successes();

Best Practices

Always Check for Failures

apex
DML.Result result = new DML()
    .toInsert(records)
    .allowPartialSuccess()
    .commitWork();

for (DML.OperationResult opResult : result.all()) {
    if (opResult.hasFailures()) {
        // Handle failures appropriately
        for (DML.Error error : opResult.errors()) {
            System.debug('Error: ' + error.message());
        }
    }
}

Use Results for Verification in Tests

apex
@IsTest
static void testAccountCreation() {
    Account account = new Account(Name = 'Test');
    
    DML.Result result = new DML()
        .toInsert(account)
        .commitWork();
    
    // Use result for comprehensive assertions
    DML.OperationResult opResult = result.insertsOf(Account.SObjectType);
    
    Assert.areEqual(1, opResult.records().size());
    Assert.areEqual(1, opResult.successes().size());
    Assert.areEqual(0, opResult.failures().size());
    Assert.isFalse(opResult.hasFailures());
    Assert.areEqual(DML.OperationType.INSERT_DML, opResult.operationType());
    Assert.isNotNull(opResult.recordResults()[0].id());
}

Released under the MIT License.