Wednesday, December 12, 2012

Caution with the ID field


The subject says it all.  It is important to know that Salesforce's Id field is a field that needs to be handled with care.  It is a read-only field.  

Here is a use case that I have encountered.  I'm going to keep using my Rig example from my last blog entry.  Suffice to know is that I have an object that stores information about rigs, which are big machineries you deploy at well sites in order to drill oil.  One of the things we capture in the Rig object is the Id of the rig owner (Rig_Owner__c), which is a lookup to the standard Account object.

Let's say all account information and rig information has been imported into Salesforce from an external system, and all data has been verified to be imported successfully.   Now one of the rigs has been sold from company A to company B.  We need to update the rig information.  When the user clicks the lookup icon to the Account, too many records are returned because the system has over 50000 account records.

It's decided we need to add a custom checkbox (or boolean) field into the Account object, called Rig_Owner_Indicator__c, and is set to true only for accounts that are rig owners.  This should help eliminate the number of records returned when we use the Lookup Filter associated with the lookup field.

After adding the column and defaulting the field values for all records to be false, now it's time we set those account records that are actually rig owners.  All rig owners are already identified in the Rig_Owner__c of the Rig object.  So one way we can run our code is:

List<Rig__c> rigs = [SELECT Rig_Owner__c FROM Rig__c];
List<Account> accounts = new List<Account>();
for (Rig__c rig : rigs)
{
    account RigAccount = new Account();
    RigAccount.Id = rig.Rig_Owner__c;
    RigAccount.Rig_Owner_Indicator__c = true;
    accounts.add(RigAccount);
}
update accounts;

However, you will get an error message that says the Id is not writeable, as this screen shot from Eclipse shows.


The offending line is
    RigAccount.Id = rig.Rig_Owner__c;

In order to fix the problem, you will need to instantiate your Id in the line where you create a new instance of the Accout SObject.  That is, if you rewrite the above as below (note the bolded line), the Apex code will execute successfully, and your Rig Owner Indicator will be populated as desired.

List<Rig__c> rigs = [SELECT Rig_Owner__c FROM Rig__c];
List<Account> accounts = new List<Account>();
for (Rig__c rig : rigs)
{
    account RigAccount = new Account(Id = rig.Rig_Owner__c);
    RigAccount.Rig_Owner_Indicator__c = true;
    accounts.add(RigAccount);
}
update accounts;

The code above will now compile.  That goes to show that when you are trying to manipulate the Id field, you need to set it when you instantiate the SObject.  Make sure you do NOT attempt to set the Id field.  Remember, it is a read-only field.

Lastly, the revised Apex code is still faulty because it will fail if more than one rig belongs to the same rig owner.  This is related to adding SObjects to List collection objects.  I will leave that to my next blog.

No comments:

Post a Comment

Please leave a comment.