Id theId = [SELECT Id FROM <table> WHERE <criteria>].Id;
This is simple and elegant and exactly what I was looking for.
Musings of a mostly developer, sometimes IT guy. Topics include Linux, web, firewall, Salesforce, etc.
Wednesday, October 3, 2012
How to avoid hard-coding Id values
So I have seen some tricks for avoiding hard-coding Id values in your Apex code, which I think is a good practice to follow, but they've always been sort of kludgey and inelegant. Today I saw one that I didn't realize you could use, and it deserves a place here:
For loops and SOQL queries
One of my favorite loops in Apex is the for(collection) loop. It's very useful for iterating through a collection. It allows you to do something like:
// Fix Asset records with null Product2Id fields.
List<Asset> assets = [SELECT Id, Product_Family__c, Product2Id
FROM Asset
WHERE Product2Id = null
];
for(Asset asset : assets)
{
// fix asset.Product2Id field here
}
update assets;
As useful as this is, it turns out that there is a better way. If you use the for([SOQL]) loop instead, Apex will actually run the SOQL query and automatically querymore each time the loop recycles. This means that you don't have to generate a complete collection and use up the heap space to store the entire query result set. This version looks like:
// Fix Asset records with null Product2Id fields.
List<Asset> updatedAssets = new List<Asset>();
for(Asset asset : [SELECT Id, Product_Family__c,Product2Id
FROM Asset
WHERE Product2Id = null
])
{
// fix asset.Product2Id here
updatedAssets.add(asset);
}
update updatedAssets;
I'm not sure how to bulkify the update without maintaining a collection of records, which sort of negates the benefits (in cases like this were all records get updated anyway) of using this form of loop. But in a case where not all records would be updated this form could save considerable heap space.
I didn't try it but it appears that there is another way to perform this operation:
// Fix Asset records with null Product2Id fields.
for(Asset[] assets : [SELECT Id, Product_Family__c,Product2Id
FROM Asset
WHERE Product2Id = null
])
{
for(Asset asset : assets)
{
// fix asset.Product2Id here
}
update assets;
}
This reduces the heap used to store the entire DML update at the expense of the number of DML operations performed. It will update records 200-at-a-time but only 200 record will be put onto the heap at a time.
The choice of which form to use is probably situationally dependent, but knowing the options obviously is the biggest part of the battle.