Apex & .NET Basics¶
Metadata-driven architecture: Code, configuration and apps are all specified as metadata in the Lightning Platform
Tightly integrated with the database.
User-interface, security, reporting, all build into the platform
No need to worry about upgrading, tuning or scaling
Basic syntax for defining a class:
private | public | global
[virtual | abstract | with sharing | without sharing]
class ClassName [implements InterfaceNameList] [extends ClassName]
{
// The body of the class
}
Check out more on classes at:
Classes | Apex Developer Guide | Salesforce Developers
Data Types¶
Primitive: Integer, Double, Long, Date, Datetime, String, Boolean, Id (autogenerated 18-character long)
Strings are values (not references)
Advanced: sObjects (Salesforce Objects)
Enums: Only keys. Ordinals are assigned automatically based on order.
public enum myEnums {
Enum1,
Enum2,
Enum3
}
// Then access them like this
Integer enumOrd = myEnums.Enum3.ordinal();
Collections¶
List (arrays in Apex are synonymous with lists, and we can use them interchangeably)
// Create directly
List<String> myStrings = new List<String> {'String1', 'String2', 'String3' };
// Create empty, assign values later
List<String> myStrings = new List<String>();
myStrings.add('String1');
myStrings.add('String2');
myStrings.add('String3');
// Create using SOQL response
List<Account> myAccounts = [SELECT Id, Name FROM Account];
// Accessing using indices
List<Account> myAccounts = [SELECT Id, Name FROM Account];
String firstAccount = myAccounts[0].Name;
Set
- No duplicates
Set<ID> accountIds = new Set<ID>{'001d000000BOaHSAA1','001d000000BOaHTAA1'};
List<Account> accounts = [SELECT Name FROM Account WHERE Id IN :accountIds];
Map
- Key-Value pairs (like python dictionary)
- Keys must be unique
// Create a map where keys are IDs,
// and the values are corresponding sObjects (Account)
Map<Id, Account> accountMap = new Map<Id, Account>(
[SELECT Id, Name FROM Account]
);
// Then the accounts can be accessed using the IDs like this
Id accId = '001d000000BOaHSAA1';
Account account = accountMap.get(accId);
Challenge¶
public class AccountUtils {
public static List<Account> accountsByState(String billingState){
List<Account> accounts = new List<Account>(
[SELECT Id, Name FROM Account WHERE BillingState=:billingState]
);
return accounts;
}
}
Understand Execution Context¶
-
What is execution context?
The execution context represents the time between when the code is executed and when it ends.
Trigger syntax
Execution context challenge solution¶
public class AccountTriggerHandler {
public static void CreateAccounts(List<Account> accounts){
for(Account account: accounts){
account.ShippingState = account.BillingState;
}
}
}
trigger AccountTrigger on Account (before insert) {
System.debug('Trigger AccountTrigger run start');
if(Trigger.isBefore && Trigger.isInsert){
AccountTriggerHandler.CreateAccounts(Trigger.New);
}
}
@isTest
public class AccountTriggerTest {
@IsTest
static void test(){
List<Account> accounts = new List<Account>();
for (Integer i = 0; i<200; i++){
accounts.add(
new Account(
Name='Account',
BillingState='CA'
)
);
}
insert accounts;
//Test.startTest();
//Database.SaveResult result = Database.insert(accounts);
//Test.stopTest();
List<Account> saved = new List<Account>(
[SELECT Id, ShippingState FROM Account where BillingState='CA']
);
for (Account a: saved){
System.assertEquals('CA', a.ShippingState, 'Shipping state is not CA');
}
}
}
Using Asynchronous APEX¶
(The following topics need their own pages, that should be linked here)
@future
methods:¶
Must be static
and void
Batch or Scheduled APEX¶
Queue-able APEX¶
Debug and Run Diagnostics¶
First level of debugging is APEX debug logs.
(Need a new page to summarise debugging methods)
Created : 25 mai 2024