5

Apologies if the title is a little vague here.

I was using the following code to attempt a insert DML:

for (ts2__Placement__c pla : selectedPlacements) {
  Timecards__c t = new Timecards__c(
    t.Approved_Rejected__c = 'New', 
    t.Week_start_date__c = startDate, 
    t.Week_enf_date__c = endDate, 
    t.Client_Name__c = pla.ts2__Client__c, 
    t.Contractor__c = pla.ts2__Employee__c, 
    t.Job_Order__c = pla.Job_Order__c,
    t.Candidate_Email__c = pla.Employee_Timesheet_Email__c, 
    t.Client_Email__c = pla.ts2__Contact_Email__c, 
    t.Placement__c = pla.Id, 
    t.Source__c = 'Something'
  );

  insert t;
}

But I was getting the following error:

Error: Compile Error: Invalid field initializer: t.Approved_Rejected__c at line 152 column 11

However, when I change the code to:

for (ts2__Placement__c pla : selectedPlacements) {
  Timecards__c t = new Timecards__c();

  t.Approved_Rejected__c = 'New';
  t.Week_start_date__c = startDate;
  t.Week_enf_date__c = endDate;
  t.Client_Name__c = pla.ts2__Client__c;
  t.Contractor__c = pla.ts2__Employee__c;
  t.Job_Order__c = pla.Job_Order__c;
  t.Candidate_Email__c = pla.Employee_Timesheet_Email__c;
  t.Client_Email__c = pla.ts2__Contact_Email__c;
  t.Placement__c = pla.Id;
  t.Source__c = 'Something';

  insert t;
}

It compiles fine. My knowledge of Apex isn't the strongest, but I naively thought these two methods did exactly the same thing? But I'm curious to know:

What's the difference between these two methods to insert (presumably this would throw the same error on all DML).

Why would one of these types fail but the other not?

Many thanks for any clarification here!

4

You're getting the error in the first case because you don't need the t. before the field names in the first syntax. This is because we already know which object you're referring to - the one you're constructing:

for (ts2__Placement__c pla : selectedPlacements) {
  Timecards__c t = new Timecards__c(
    Approved_Rejected__c = 'New', 
    Week_start_date__c = startDate, 
    Week_enf_date__c = endDate, 
    Client_Name__c = pla.ts2__Client__c, 
    Contractor__c = pla.ts2__Employee__c, 
    Job_Order__c = pla.Job_Order__c,
    Candidate_Email__c = pla.Employee_Timesheet_Email__c, 
    Client_Email__c = pla.ts2__Contact_Email__c, 
    Placement__c = pla.Id, 
    Source__c = 'Something'
  );

  insert t;
}

The Salesforce docs have a brief example of this syntax.

In terms of the difference between the two, they're just two ways to create an Apex object.

The first uses the built-in sObject Named Parameter constructor, which just means that we can use the syntax above to concisely set the field values when we're creating the object.

The latter creates a "blank" object, then sets the field values on the object after it's created.

After you've created and set the objects' field values with either approach, they're equivalent, and they'll act the same when insert'ed with DML.

  • Rookie error on my part there. Is there any difference between these two methods of DML though, or do they literally do the same thing as I initially thought? – Dan Jones Sep 28 '15 at 9:59
  • 1
    They're just two ways to create an object; once the objects are created, they're equivalent, and there's no difference in the way they act e.g. when used with DML. – Rob Sep 28 '15 at 10:02
  • Beautiful. Thought there might be some caveat between the two. Thanks for clearing this up. – Dan Jones Sep 28 '15 at 10:03
8

Yes both the ways have significant different in terms of CPU utilization. Just ran the below code snippet in Execute Anonymous block in Developer Console and got the debug logs.

System.debug(Datetime.now() + '-' + Datetime.now().milliSecond());
for(Integer i=0; i<1000; i++){
    Account a = new Account(name = 'test');    
}
System.debug(Datetime.now() + '-' + Datetime.now().milliSecond());
for(Integer i=0; i<1000; i++){
    Account a = new Account();    
    a.name = 'test';
}
System.debug(Datetime.now() + '-' + Datetime.now().milliSecond());

15:45:25:038 USER_DEBUG [1]|DEBUG|2015-09-28 10:15:25-456

15:45:25:122 USER_DEBUG [5]|DEBUG|2015-09-28 10:15:25-540

15:45:25:229 USER_DEBUG [10]|DEBUG|2015-09-28 10:15:25-648

First method took 84 milli seconds for 1000 iterations and the second method took 108 milli seconds for 1000 iterations.

This statistics is for a single field. If you have numerous fields, this varies much significantly.

Reason for this difference is, the first method initializes the sObject first and uses its instance variable to assign the value to the fields which utilizes much of CPU.

But in second method, the sObject is initialized with all its fields assigned with values thus utilizing less of CPU.

Hope it helps you to understand better.

  • I see! That's really interesting. I wouldn't have thought CPU time would've been affected although that's reason enough to use the former method as opposed to the latter way to me. – Dan Jones Sep 28 '15 at 10:29
  • 1
    Yes. To create records in a for loop, you should consider the CPU time limit as well. – Vigneshwaran G Sep 28 '15 at 10:32
  • 3
    @Poet Also note that the per-field cost goes up with the t.Field = value method. If you have 20 fields you're creating in a loop, you'll notice a significant CPU savings, probably close to a few hundred milliseconds per record, using the SObject constructor method. – sfdcfox Sep 28 '15 at 11:19
  • I see! Does this take longer because the object is being generated and then fields are being assigned, rather than assigning fields as it's being created? – Dan Jones Sep 28 '15 at 11:24
  • Yes. If you do a blank initialization and then assign values Server do two works. But assigning values while initialization makes server to do single work so reduced CPU time. – Vigneshwaran G Sep 28 '15 at 15:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.