Developer Fundamentals · Topic 3 of 4
The Data Model for Developers
Salesforce data model for Apex developers: objects, field API names, lookup and master-detail relationships, relationship names, external IDs and upsert.
- 4 min
- Custom objects and fields end in
__c; custom relationship names end in__r. - Child to parent uses dot notation; parent to child uses a subquery with the plural relationship name.
- Master-detail: no owner on the detail, cascade delete, roll-ups; lookup: independent records.
What it is
The data model is the set of objects, fields and relationships that store an org's data. In Apex every object is an sObject type, such as Account or Invoice__c, and every field is reached by its API name.
Developers need to know how relationships appear in code and queries, and how external IDs let code and integrations match records from other systems without knowing Salesforce Ids.
How it works
Naming in code
| Item | Example API name |
|---|---|
| Standard object | Account, Contact, Case |
| Custom object | Invoice__c |
| Custom field | Amount__c |
| Custom relationship field (holds the Id) | Account__c |
| Custom relationship name (used to traverse) | Account__r |
| Custom metadata type | Discount_Rate__mdt |
| Platform event | Order_Placed__e |
Relationship types
| Type | Key behaviour |
|---|---|
| Lookup | Loose link; child keeps its own owner and sharing; parent delete clears the field or is blocked |
| Master-detail | Detail has no owner, inherits sharing, is deleted with the master; master can have roll-up summaries |
| Many-to-many | A junction object with two master-detail fields |
| Hierarchical | A lookup from User to User |
| External lookup | Links to an external object by its external ID |
Relationships in SOQL
// Child to parent: dot notation
List<Contact> cs = [SELECT LastName, Account.Name FROM Contact];
// Parent to child: subquery using the child relationship name
List<Account> accs = [SELECT Name, (SELECT LastName FROM Contacts) FROM Account];
// Custom relationship: __r in both directions
List<Invoice__c> inv = [SELECT Name, Customer__r.Name FROM Invoice__c];
List<Customer__c> cust = [SELECT Name, (SELECT Name FROM Invoices__r) FROM Customer__c];
The child relationship name for a standard relationship is plural (Contacts, Cases, Opportunities). For a custom one it is the name set on the field plus __r.
External IDs
An External ID is a custom field (text, number, email or auto number) flagged to hold a key from another system. External ID fields are indexed, so queries filtering on them are fast.
They are used for:
- Upsert: insert or update depending on whether a matching record exists.
- Setting relationships without a query: link a child to a parent by the parent's external ID.
// Upsert by external ID
List<Account> accs = new List<Account>{ new Account(Name = 'Acme', ERP_Id__c = 'A-100') };
upsert accs Account.ERP_Id__c;
// Link a Contact to an Account by its external ID, with no SOQL
Contact c = new Contact(LastName = 'Ng', Account = new Account(ERP_Id__c = 'A-100'));
insert c;
If the external ID value matches more than one record, the upsert fails for that record with a duplicate error. Marking the field Unique prevents that.
Custom settings and custom metadata types
| Feature | Custom metadata type | Custom setting |
|---|---|---|
| Records deployable as metadata | Yes | No (data must be loaded) |
| Read in Apex | Rate__mdt.getInstance('Standard') or getAll(), no SOQL limit used | Settings__c.getInstance() or getOrgDefaults(), cached |
| Hierarchy by profile or user | No | Yes, hierarchy custom settings |
| Typical use | App configuration that moves between orgs | User or profile-specific switches |
A worked example
An ERP sends nightly invoice files containing an account number, never a Salesforce Id. The developer adds ERP_Id__c to Account as an External ID and Unique, and ERP_Invoice_No__c to Invoice__c as an External ID. The load runs upsert invoices Invoice__c.ERP_Invoice_No__c; and sets each invoice's parent with Account__r = new Account(ERP_Id__c = row.accountNo). No query for Account Ids is needed, and rerunning the file updates rather than duplicates.
When a question says "without querying for the Id" or "records from an external system", look for an External ID with upsert.
How the exam asks about this
- "Query each Account with its Contacts." A parent-to-child subquery using
Contacts. - "Load records again without creating duplicates." Upsert on an External ID field.
- "Configuration records must deploy with the code." Custom metadata types.
What to remember for the exam
- Custom objects and fields end in
__c; custom relationship names end in__r. - Child to parent uses dot notation; parent to child uses a subquery with the plural relationship name.
- Master-detail: no owner on the detail, cascade delete, roll-ups; lookup: independent records.
- External IDs are indexed and power upsert and relationship matching without SOQL.
- Custom metadata records deploy as metadata and are read without using SOQL queries.
In a subquery you must use the relationship name (Contacts, Invoices__r), not the object name (Contact, Invoice__c). Using the object name is a compile error.
Common mistakes
Using __c to traverse a relationship. Customer__c holds the Id; Customer__r.Name reaches the parent's field.
Querying for parent Ids before linking records. An external ID reference does it without a query.
Choosing custom settings for configuration that must deploy. Custom setting records are data; custom metadata records deploy.
Check yourself
How do you query each Account with its related Contacts in one SOQL statement?
SELECT Name, (SELECT LastName FROM Contacts) FROM Account.What does
upsert records Account.ERP_Id__c;do?It updates records whose ERP_Id__c matches an existing account and inserts the rest.
Why does reading custom metadata with
getInstance()suit trigger code?It does not count against the SOQL query limit, and its records deploy with the code.
Topic 3 of 4 in Developer Fundamentals
Test yourself on Developer Fundamentals
The full Salesforce Platform Developer question bank has 645 questions, with timed practice exams and an explanation for every answer.
This study guide is independent and is not affiliated with, endorsed by, or sponsored by Salesforce. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.