Free sample · answers included
Free Salesforce Platform Developer II
Practice Questions
18 free Platform Developer II practice questions from our bank of 300 reviewed questions, picked across all 5 official exam sections in proportion to their weight. Each one shows the correct answer, why it is right and why the others are wrong, and the official documentation it was checked against.
Last updated
What is the Platform Developer II exam like?
60+5
Scored + unscored questions
120 min
Time limit
70%
Passing score
$200
Registration (retake $100)
Confirm current details in the official Platform Developer II exam guide.
Questions by exam section
Heavier sections get more questions, the same way the real exam and our 60-question practice exams are weighted.
Advanced Developer Fundamentals
15% of the examQuestion 1 · Medium · Choose 2
Northern Trail Outfitters shares each Expedition__c record, whose organization-wide default is Private, with every member of the expedition's crew. The current trigger inserts one Expedition__Share row for each crew member on each of 60,000 expeditions. Crews have up to 300 members, people change crews daily, and every change inserts or deletes thousands of share rows. The developer plans to create one public group for each crew. Which two steps should the new design include? Choose 2 answers.- A.Insert one Expedition__Share row per expedition, with the crew's group ID in
UserOrGroupIdand an Apex sharing reason inRowCause. - B.Set
AccessLeveltoAllon each group share so that crew members can also transfer, share, and delete the expeditions they work on. - C.Have Apex create a criteria-based sharing rule for each new crew so that the platform maintains the group shares automatically.
- D.When a person joins or leaves a crew, insert or delete that user's GroupMember record instead of changing Expedition__Share rows.
- E.Update the
UserOrGroupIdof each existing Expedition__Share row to the new group's ID instead of inserting new share rows.
Show the answer and explanationHide the answer
Correct answers: A. Insert one Expedition__Share row per expedition, with the crew's group ID inUserOrGroupIdand an Apex sharing reason inRowCause.; D. When a person joins or leaves a crew, insert or delete that user's GroupMember record instead of changing Expedition__Share rows.A share row'sUserOrGroupIdcan reference a public group, so sharing each expedition once with the crew's group, using an Apex sharing reason, replaces hundreds of per-user rows. Crew changes then only add or remove GroupMember records, which represent the members of a public group, and the expedition shares stay the same; because GroupMember is a setup object, that DML must run in a separate transaction from DML on records such as Expedition__c. TheAllaccess level can't be granted through Apex. Apex can't create criteria-based sharing rules.UserOrGroupIdcan't be updated on an existing share row, so old rows must be deleted and new ones inserted.- A.Insert one Expedition__Share row per expedition, with the crew's group ID in
Question 2 · Medium · Choose 2
Universal Containers has multiple currencies enabled. A developer at Universal Containers reviews this query, which runs for a user whose personal currency is EUR:
Which two statements about the query are true? Choose 2 answers.SELECT Name, Amount, convertCurrency(Amount) convertedAmount FROM Opportunity WHERE Amount > USD50000- A.
Amountis returned in the org's corporate currency. - B.The query fails because the result of
convertCurrency()can't be given an alias. - C.
convertedAmountcontains each opportunity's amount converted to the user's currency, EUR. - D.The filter returns opportunities whose amount is greater than the equivalent of 50,000 US dollars, whatever each record's currency is.
- E.The filter compares the number 50,000 to each amount without taking the record's currency into account.
Show the answer and explanationHide the answer
Correct answers: C.convertedAmountcontains each opportunity's amount converted to the user's currency, EUR.; D. The filter returns opportunities whose amount is greater than the equivalent of 50,000 US dollars, whatever each record's currency is.convertCurrency()in the SELECT clause converts currency fields to the user's currency, and it supports an alias such asconvertedAmount. In the WHERE clause,convertCurrency()isn't allowed, so SOQL uses an ISO-code prefix:Amount > USD50000returns records whose amount is greater than the equivalent of USD 50,000. Only a filter written without the ISO code compares the plain number 50,000 to each amount regardless of the record's currency, so the statement that the filter ignores the record's currency is wrong. The unwrappedAmountfield comes back in the record's own currency, not the corporate currency, and aliasingconvertCurrency()doesn't cause an error.- A.
Question 3 · Harder
Ursa Major Solar's Lightning web component lists the service regions stored in the Service_Region__mdt custom metadata type. It calls this Apex method:
The org uses the default Schema Settings. The component shows the regions to administrators, but it doesn't work for field technicians. The security team doesn't want to grant technicians access to the custom metadata type. What should the developer do?public with sharing class RegionController { @AuraEnabled(cacheable=true) public static List<Service_Region__mdt> getRegions() { return [SELECT DeveloperName, Label, Region_Code__c FROM Service_Region__mdt]; } }- A.Declare the class
without sharingso that the query runs in system mode and returns the records to every user - B.Add
WITH SYSTEM_MODEto the query so that the technicians' access to the custom metadata type isn't checked - C.Copy the field values into a wrapper class or a list of strings, and return that instead of the records
- D.Replace the query with
Service_Region__mdt.getAll().values(), which doesn't count against SOQL limits
Show the answer and explanationHide the answer
Correct answer: C. Copy the field values into a wrapper class or a list of strings, and return that instead of the recordsThe Restrict access to custom metadata types preference is enabled by default, so users need access granted through profiles or permission sets, and functionality that runs in user mode, such as an Aura or Lightning component receivingService_Region__mdtrecords from an@AuraEnabledmethod, checks that access. Apex runs in system mode and isn't affected by the preference, so returning the values in a wrapper class or as strings works, because the result is no longer the custom metadata type. Thewith sharingkeyword doesn't affect access to custom metadata types, and the query already runs in system mode, so neitherwithout sharingnorWITH SYSTEM_MODEchanges what the component receives.getAll()still returns Service_Region__mdt records, so the same access check applies.- A.Declare the class
Process Automation, Logic, and Integration
27% of the examQuestion 4 · Medium
AW Computing sells a managed package that calculates shipping costs. Subscribers can supply their own calculation logic by writing a global class that implements the package's globalShippingCalculatorinterface, and they enter the class name in a custom metadata record. How should the package instantiate the subscriber's class at run time?- A.Call
Schema.getGlobalDescribe().get(className)and cast the result toShippingCalculator. - B.Get the class's type with
Type.forName, then callnewInstance()and cast the result toShippingCalculator. - C.Query the
ApexClassobject for the class body and run it withDatabase.query. - D.Use dynamic DML to insert a record of the subscriber class type and cast it to
ShippingCalculator.
Show the answer and explanationHide the answer
Correct answer: B. Get the class's type withType.forName, then callnewInstance()and cast the result toShippingCalculator.Type.forNamereturns theSystem.Typefor a public or global class name, andnewInstance()creates an instance that can be cast to the interface. Salesforce documents this pattern for packages that read the name of an implementation class from the subscriber's configuration. From an installed managed package, use the two-argumentType.forName(namespace, name)with an empty or null namespace when the subscriber org has no namespace, because the one-argument form returns null there.Schema.getGlobalDescribe()returns only sObject tokens, not Apex classes. QueryingApexClassreturns metadata about a class, andDatabase.queryruns SOQL, not Apex code. Dynamic DML creates and saves sObject records and can't instantiate Apex classes.- A.Call
Question 5 · Harder
Refer to the query below:
A developer at Northern Trail Outfitters loops through the AggregateResult rows to build a chart that must include leads with no lead source. Two rows have a null LeadSource: one for leads with no lead source and one grand total. How should the developer identify the grand-total row?SELECT LeadSource, COUNT(Id) cnt FROM Lead GROUP BY ROLLUP(LeadSource)- A.Add GROUPING(LeadSource) to the SELECT list and treat the row where it returns 1 as the grand-total row.
- B.Change the clause to GROUP BY CUBE(LeadSource), which labels subtotal rows with the text Total.
- C.Add WHERE LeadSource != null so that only the grand-total row has a null LeadSource.
- D.Treat the first row returned as the grand total, because ROLLUP always returns subtotal rows first.
Show the answer and explanationHide the answer
Correct answer: A. Add GROUPING(LeadSource) to the SELECT list and treat the row where it returns 1 as the grand-total row.GROUP BY ROLLUP adds subtotal rows whose grouping field is null, and GROUPING(fieldName) returns 1 when a row is a subtotal for that field and 0 otherwise, which Salesforce describes as the best way to differentiate aggregated data from subtotals. GROUP BY CUBE also returns subtotal rows with null grouping values; it doesn't add a Total label. Filtering out null LeadSource values in WHERE removes the leads with no lead source from the counts, which breaks the chart requirement and changes the grand total. Result order isn't guaranteed without ORDER BY, and in the documented examples the grand total appears as the last row, not the first.Question 6 · Medium
A mobile app at Cloud Kicks must send one HTTP request to Salesforce that creates a Store_Visit__c record, creates a Visit_Note__c record that looks up to the new visit, and updates the existing Account record'sLast_Visit__clookup with the new visit's ID. If any step fails, none of the changes can be saved, and the team doesn't want to write custom Apex. Which REST API approach should the developer use?- A.The Composite Batch resource with
haltOnErrorset to true and one subrequest for each of the three records - B.The Composite resource with
allOrNoneset to true and@{refVisit.id}references in later subrequests - C.The sObject Tree resource, with the visit note nested under the visit and the account nested under the note
- D.The sObject Collections resource, sending all three records in a single request with
allOrNoneset to true
Show the answer and explanationHide the answer
Correct answer: B. The Composite resource withallOrNoneset to true and@{refVisit.id}references in later subrequestsThe Composite resource runs a series of subrequests in one call, and a later subrequest can use the output of an earlier one through its reference ID, such as@{refVisit.id}. WithallOrNoneset to true, an error in any subrequest rolls back the entire composite request. Composite Batch subrequests are independent and can't pass information to each other, andhaltOnErroronly stops the remaining subrequests; commits made by earlier subrequests aren't rolled back. sObject Tree creates new parent-child record trees, so it can't update the existing account. An sObject Collections request performs one kind of operation, such as create with POST or update with PATCH, so it can't create the visit and update the account together.- A.The Composite Batch resource with
Question 7 · Medium
At Universal Containers, an after insert trigger on Order publishes anOrder_Placed__eplatform event, which uses the default publish behavior. Sometimes a subscriber can't find the order when it queries for it. Events are also received for orders whose transaction later failed and rolled back. What should the developer do?- A.Change the event's publish behavior to Publish After Commit.
- B.Call
Database.setSavepoint()beforeEventBus.publish()and roll back the event if the order fails. - C.Increase the batch size of the subscriber's Apex trigger to 2,000 events.
- D.Move the
EventBus.publish()call from the after insert trigger to a before insert trigger.
Show the answer and explanationHide the answer
Correct answer: A. Change the event's publish behavior to Publish After Commit.With Publish Immediately, the default, the event message is published as soon as the publish call runs, whether or not the transaction succeeds. A subscriber can therefore receive it before the order is committed, or for an order that's rolled back. Publish After Commit publishes the message only after the transaction commits successfully, and doesn't publish it if the transaction fails. A savepoint can't undo a Publish Immediately message, because the message is published when the publish call runs, regardless of whether the transaction succeeds. The subscriber's batch size doesn't affect when messages are published. A before insert trigger runs in the same uncommitted transaction, so moving the publish call there doesn't fix the timing.Question 8 · Medium · Choose 2
Get Cloudy Consulting has one large record-triggered flow on Shipment__c with loops, collection filters, and cross-object updates. During nightly Bulk API loads of 10,000 records, the flow hits CPU time limits. The architect proposes moving this logic to an Apex trigger framework. Which two considerations support the proposal? Choose 2 answers.- A.Apex offers Map and Set collections and finer control over queries, which make bulk processing more efficient than Flow loops.
- B.Apex can cache expensive query results in static variables and reuse them across invocations in the same transaction.
- C.Splitting the flow into several smaller, well-conditioned flows would remove the CPU time problem without any code.
- D.Apex triggers are exempt from governor limits because Apex code in triggers runs in system mode.
- E.Record-triggered flows can't process more than 200 records from a single Bulk API load.
Show the answer and explanationHide the answer
Correct answers: A. Apex offers Map and Set collections and finer control over queries, which make bulk processing more efficient than Flow loops.; B. Apex can cache expensive query results in static variables and reuse them across invocations in the same transaction.Salesforce's automation guidance rates Apex as the recommended tool for high-performance bulk processing because it provides Map and Set data structures and more control over query optimization, while Flow lacks native maps and sets. Apex can also deduplicate expensive work by caching data in static variables for the duration of the transaction, something Flow can't do across invocations. Splitting a mega-flow into multiple flows doesn't have a major performance impact; the gains come from before-save updates and precise entry conditions. Apex in triggers is always subject to governor limits; system mode concerns data access, not limits. Flows do run for Bulk API loads, which are processed in chunks rather than rejected.
User Interface
20% of the examQuestion 9 · Harder
Northern Trail Outfitters has a Lightning web component that shows quote line items and lets a sales rep apply a discount.getLineItemsis a cacheable Apex method, andapplyDiscountupdates the line items. Refer to the component's JavaScript:
The discount is saved, but the component keeps showing the old prices until the page is reloaded. What should the developer do?import { refreshApex } from '@salesforce/apex'; // getLineItems and applyDiscount are imported from QuoteController export default class QuoteLines extends LightningElement { @api recordId; lineItems; @wire(getLineItems, { quoteId: '$recordId' }) wiredLines({ data }) { if (data) { this.lineItems = data; } } async handleDiscount() { await applyDiscount({ quoteId: this.recordId }); await refreshApex(this.lineItems); } }- A.Add
cacheable=truetoapplyDiscountso that both methods share the same client-side cache. - B.Replace the
refreshApex()call withnotifyRecordUpdateAvailable()for the quote record. - C.Store the value the wire service passes to
wiredLinesin a property, then pass that property torefreshApex(). - D.Decorate
lineItemswith@trackso the component rerenders when the discount is applied.
Show the answer and explanationHide the answer
Correct answer: C. Store the value the wire service passes towiredLinesin a property, then pass that property torefreshApex().refreshApex()must receive an object that an Apex@wirepreviously emitted; for a wired function, that's the argument the function receives, not thedataextracted from it. Saving that value (for example,this.wiredResult = result) and callingrefreshApex(this.wiredResult)makes the wire requery the server and provision fresh line items.applyDiscountchanges data, so it can't be marked cacheable, and caching it wouldn't refresh another method's results anyway.notifyRecordUpdateAvailable()refreshes records in the Lightning Data Service cache, but Lightning Data Service doesn't manage data provisioned by Apex, so the wired line items would stay stale.@trackonly affects how changes to a field are observed; the real problem is that no new data is requested.- A.Add
Question 10 · Harder
In a Lightning console app at Cumulus Financial, a Lightning web component on a case workspace subtab subscribes to a message channel:
The component receives messages only while its subtab is the one the agent is viewing. It must receive alerts even when the agent is working in another tab. What should the developer do?@wire(MessageContext) messageContext; connectedCallback() { if (!this.subscription) { this.subscription = subscribe( this.messageContext, CASE_ALERT_CHANNEL, (message) => this.handleAlert(message) ); } }- A.Pass
{ scope: APPLICATION_SCOPE }, imported fromlightning/messageService, as the fourth argument tosubscribe(). - B.Pass
{ scope: APPLICATION_SCOPE }as the fourth argument topublish()in the publishing component. - C.Replace
@wire(MessageContext)withcreateMessageContext()so the subscription isn't tied to the active tab. - D.Move the
subscribe()call into the constructor so the subscription exists before the subtab renders.
Show the answer and explanationHide the answer
Correct answer: A. Pass{ scope: APPLICATION_SCOPE }, imported fromlightning/messageService, as the fourth argument tosubscribe().By default, a Lightning message service subscriber receives messages only in the application's active area, such as the selected navigation or workspace tabs and utility items. To receive messages from anywhere in the application, importAPPLICATION_SCOPEfromlightning/messageServiceand pass{ scope: APPLICATION_SCOPE }as the optional fourthsubscriberOptionsargument tosubscribe(). Scope is a subscriber option, so passing it topublish()doesn't change which subscribers receive the message. For Lightning web components, scoping is available only with@wire(MessageContext), andcreateMessageContext()is for API modules that don't extendLightningElement. A component must be attached to the DOM before it can use theMessageContextproperty, so subscribing in the constructor is too early.- A.Pass
Question 11 · Harder
A developer at Get Cloudy Consulting places eight project tiles inside<lightning-layout multiple-rows>. Each tile is wrapped in this layout item:
How wide is each tile when a user views the component on a tablet?<lightning-layout-item size="12" small-device-size="6" large-device-size="3"> <c-project-tile></c-project-tile> </lightning-layout-item>- A.Full width, because
size="12"applies to every device type. - B.One quarter of the width, because
large-device-sizeapplies to tablets and larger devices. - C.The width of its content, because the device-size attributes are ignored when
medium-device-sizeisn't set. - D.Half the width, because
small-device-sizeapplies to devices of that size and larger, andmedium-device-sizeisn't set.
Show the answer and explanationHide the answer
Correct answer: D. Half the width, becausesmall-device-sizeapplies to devices of that size and larger, andmedium-device-sizeisn't set.Forlightning-layout-item,small-device-sizetypically targets smart phones,medium-device-sizetargets tablets, andlarge-device-sizetargets desktops or larger devices. The device-size attributes are additive and apply to devices of the specified size and larger, so with nomedium-device-size, a tablet uses thesmall-device-sizevalue of 6 out of 12 columns, which is half the width. When bothsizeandsmall-device-sizeare set,sizeapplies only to small mobile phones.large-device-sizeapplies to desktops and larger, not tablets. A missingmedium-device-sizedoesn't make the item fall back to its content width; the smaller device setting carries up.- A.Full width, because
Question 12 · Medium
Refer to this Aura component at Northern Trail Outfitters:
The<aura:component implements="flexipage:availableForRecordHome"> <ltng:require scripts="{!$Resource.mapLib + '/leaflet.js'}" styles="{!$Resource.mapLib + '/leaflet.css'}"/> <aura:handler name="init" value="{!this}" action="{!c.doInit}"/> <div aura:id="map" class="trail-map"></div> </aura:component>doInitaction creates the map with the library's globalLobject. Users intermittently see an error thatLis undefined. What should the developer do?- A.Replace
$Resource.mapLib + '/leaflet.js'withURLFOR($Resource.mapLib, 'leaflet.js')in thescriptsattribute. - B.Add a
<script>tag that references the static resource directly in the component markup. - C.Create the map in an action set by
afterScriptsLoaded="{!c.initMap}"onltng:requireinstead of indoInit. - D.Load the library in
doInitby calling$A.get('$Resource.mapLib')before the code that creates the map.
Show the answer and explanationHide the answer
Correct answer: C. Create the map in an action set byafterScriptsLoaded="{!c.initMap}"onltng:requireinstead of indoInit.Scripts loaded withltng:requireload asynchronously, so they probably aren't available yet when theinithandler runs. TheafterScriptsLoadedaction runs after the scripts are loaded and the component is rendered, so the map should be created there. Aura has nothing likeURLFOR(); string concatenation with$Resource, as the component already uses, is the correct syntax. You can't use a<script>tag in an Aura component, a restriction that mitigates the risk of cross-site scripting attacks.$A.get('$Resource.mapLib')only returns the resource's URL; it doesn't load or run the script.- A.Replace
Testing, Debugging, and Deployment
20% of the examQuestion 13 · Medium
A developer at Universal Containers wrote this Jest test for ac-greetingcomponent. Its template renders<p>Hello, {name}</p>, and itsnameproperty is decorated with@apiand defaults to'World'.
The test fails because the paragraph still reads "Hello, World". Which change fixes the test?it('greets the user by name', () => { const element = createElement('c-greeting', { is: Greeting }); document.body.appendChild(element); element.name = 'Ada'; const p = element.shadowRoot.querySelector('p'); expect(p.textContent).toBe('Hello, Ada'); });- A.Query the paragraph with
document.querySelector('p')instead ofelement.shadowRoot.querySelector('p'). - B.Make the test function
asyncand addawait Promise.resolve();after settingelement.name, before querying the paragraph. - C.Call
element.connectedCallback()after settingelement.nameto force the component to rerender. - D.Decorate
namewith@trackinstead of@apiso the template updates synchronously.
Show the answer and explanationHide the answer
Correct answer: B. Make the test functionasyncand addawait Promise.resolve();after settingelement.name, before querying the paragraph.When a component's state changes after it's inserted into the DOM, the DOM updates asynchronously, so the test must wait for a resolved promise before checking the result. Setting the property beforeappendChild()would also work, because the component then renders synchronously.document.querySelector()can't see into the component's shadow tree;element.shadowRootis the test-only API for inspecting it, so that change returns null. Tests don't call lifecycle hooks to force a rerender. Replacing@apiwith@trackwould removenamefrom the component's public API, and rerendering would still be asynchronous.- A.Query the paragraph with
Question 14 · Harder
At Northern Trail Outfitters, Shipment_Line__c is the detail object in a master-detail relationship with Shipment__c. A before delete trigger on Shipment_Line__c creates an Archive__c record for each deleted line. Archive records are created when users delete individual lines, but not when a user deletes a whole shipment, even though its lines are deleted too. What is the cause?- A.Cascading deletes don't invoke triggers on the child records, because only records that initiate a delete cause trigger evaluation; the archiving must also be handled by a delete trigger on Shipment__c.
- B.Before delete triggers on detail objects run only for records deleted through the API, not for deletions made in the user interface.
- C.The Shipment_Line__c trigger runs, but Archive__c records inserted during a cascade delete are rolled back when the master record is deleted.
- D.The trigger must be changed from before delete to after delete, because before delete triggers never run when a parent record's deletion cascades to its children, but after delete triggers do run for the cascaded deletion in that case.
Show the answer and explanationHide the answer
Correct answer: A. Cascading deletes don't invoke triggers on the child records, because only records that initiate a delete cause trigger evaluation; the archiving must also be handled by a delete trigger on Shipment__c.Some system operations don't invoke triggers, and cascading deletes are one of them: only the records that initiate a delete cause trigger evaluation. When a user deletes a Shipment__c record, its Shipment_Line__c records are removed by the cascade, so no Shipment_Line__c trigger runs. A before delete trigger on Shipment__c can query the lines before they're removed and archive them. The trigger doesn't depend on whether a direct delete came from the API or the UI, no Archive__c records are rolled back because the trigger never runs, and switching to after delete doesn't help for the same reason.Question 15 · Easier
Ursa Major Solar'sIncentiveCalculatorclass has a private static method,tierFor(Decimal kilowatts), that contains complex branching logic. A developer wants a unit test to call this method directly, but the method must stay inaccessible to other production classes. What should the developer do?- A.Change the method's access modifier to
publicand add a comment that it's for testing only. - B.Annotate the test class with
@IsTest(SeeAllData=true)so it can call private methods. - C.Annotate the method with
@TestVisible. - D.Declare
IncentiveCalculatorasglobalso that test classes can access its private members.
Show the answer and explanationHide the answer
Correct answer: C. Annotate the method with@TestVisible.@TestVisiblelets test methods access private or protected members of another class, including methods, member variables, and inner classes, and it doesn't change their visibility for non-test code. Making the methodpublicexposes it to every class that can seeIncentiveCalculator, which breaks the requirement.SeeAllData=truecontrols access to org data, not access to class members. Declaring the classglobalwidens access to the class itself but doesn't expose its private members.- A.Change the method's access modifier to
Performance
18% of the examQuestion 16 · Harder
The Delivery__c object at Northern Trail Outfitters holds 4 million records. A developer must pick one filter for a query that runs in a trigger, and the query must be selective. Based on the query optimizer's index thresholds, which filter is selective?- A.
WHERE Region__c = 'West', whereRegion__chas a custom index and the filter matches 350,000 records - B.
WHERE CreatedDate = LAST_N_DAYS:90, which matches 700,000 records - C.
WHERE Tracking_Code__c = :code, whereTracking_Code__cis a custom text field without an index and the filter matches 5 records - D.
WHERE Status__c != 'Delivered', whereStatus__chas a custom index and the filter matches 100,000 records
Show the answer and explanationHide the answer
Correct answer: B.WHERE CreatedDate = LAST_N_DAYS:90, which matches 700,000 recordsA filter is selective only when it's on an indexed field, uses an operator the index supports, and matches fewer records than the index threshold. For a standard index such as CreatedDate, the threshold is 30% of the first million records plus 15% of the remaining records, up to 1 million; for 4 million records that's 750,000, so a filter that matches 700,000 records qualifies. A custom index is used only when the filter matches less than 10% of the records, up to a maximum of 333,333, so 350,000 matches are too many. A filter on an unindexed field isn't selective however few records it matches, because the optimizer has no index to use. A custom index typically isn't used with a negative operator such as!=.- A.
Question 17 · Easier
A before insert trigger handler at Cloud Kicks sets a field on each new Order__c record based on the running user's role:
Imports of more than 100 orders fail withfor (Order__c o : orders) { User u = [SELECT UserRoleId FROM User WHERE Id = :UserInfo.getUserId()]; o.Created_By_Role__c = u.UserRoleId; }System.LimitException: Too many SOQL queries: 101. Which change removes the query from the transaction entirely, rather than just moving it outside the loop?- A.Add
LIMIT 1to the query so that each iteration retrieves only one row. - B.Move the query into a
@futuremethod so that it runs with higher governor limits. - C.Query all users with
SELECT Id, UserRoleId FROM Userbefore the loop, and search the list for the running user. - D.Call
UserInfo.getUserRoleId()once before the loop, and assign the stored value inside the loop.
Show the answer and explanationHide the answer
Correct answer: D. CallUserInfo.getUserRoleId()once before the loop, and assign the stored value inside the loop.The query returns the same value for every order, yet it runs once per record.UserInfo.getUserRoleId()returns the context user's role ID without a SOQL query, and calling it once before the loop removes the repeated work entirely.LIMIT 1still runs one query per order, so the limit is still exceeded. A future method runs later in a separate transaction, so it can't supply the value before the orders are saved. Querying every user retrieves many unnecessary rows and adds a search through the list, when the value is already available without any query.- A.Add
Question 18 · Medium
A developer at Get Cloudy Consulting built a Lightning web component for the Project__c record page that shows the project's status, budget, and end date. The component uses this markup:
The Project__c page layout contains more than 150 fields, and the component loads slowly. What should the developer do?<lightning-record-form record-id={recordId} object-api-name="Project__c" layout-type="Full" mode="readonly"> </lightning-record-form>- A.Replace the component with an Apex method that queries every Project__c field.
- B.Replace
layout-typewith afieldsattribute that lists only the three fields the component displays. - C.Change
modeto "view" so that the form loads in view mode. - D.Wrap the form in a
<template lwc:if>whose condition is set to true inrenderedCallback().
Show the answer and explanationHide the answer
Correct answer: B. Replacelayout-typewith afieldsattribute that lists only the three fields the component displays.Salesforce recommends specifying fields instead of a layout whenever possible to improve performance, because a layout makes the component load every field that the administrator assigns to it. Listing only the three fields in thefieldsattribute reduces the data that the form requests and renders. Querying every field in Apex moves the same problem to the server and gives up Lightning Data Service caching. Changing the mode controls whether users can edit fields inline, not how many fields load. Rendering the form afterrenderedCallback()only delays it and triggers an extra render.
Where to go after these 18 questions
Free practice questions for other Salesforce Developer certifications
Ready for a full Platform Developer II practice exam?
Take a timed 60-question exam drawn from all 300 reviewed questions in the real exam's section mix, then drill the sections you miss.