function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
mxalix258mxalix258 

CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY

I'm trying to write a test class for a trigger that performs a new record insertion. The trigger is before update, and will insert a record on an associate object. When writing the test class, I am getting this error:

 

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, CreateOnboardingRecord: execution of BeforeUpdate

caused by: System.DmlException: Insert failed. First exception on row 0 with id 00Tc0000004Q0dqEAC; first error: INVALID_FIELD_FOR_INSERT_UPDATE, cannot specify Id in an insert call: [Id]

Class.CreateOnboardingFromApplication.createOnboard: line 121, column 1
Trigger.CreateOnboardingRecord: line 7, column 1: []

 

 Any idea where I may be going wrong?

 

Thanks!

Best Answer chosen by Admin (Salesforce Developers) 
davidjgriffdavidjgriff

Something like this should do it. (Forgive any typos or compile errors as I have not tested/compiled this code)

 

//Iterate through the save results
for(Integer i = 0;i<srl.size();i++){
	
	Database.SaveResult sr = srl[i];
	
    if(sr.isSuccess()){
		On_Off_Boarding__c postrecord = obrecordToInsert[i];
				//creates the new feed post
				FeedItem post = new FeedItem ();
				post.ParentId = postrecord.Associated_Application__c;
				post.Body = 'The onboarding record for ' + postrecord.name + ' has been created';
				post.LinkUrl = URL.getSalesforceBaseUrl().toExternalForm() + '/' + postrecord.Id;
				post.Title = 'Onboarding Record';
				
				feedpost.add(post);
				
				Task obtask = new Task ();
				obtask.WhatId = postrecord.Associated_Application__c;
				obtask.OwnerId = UserInfo.getUserId();
				obtask.Subject = 'Onboarding record created';
				obtask.status = 'Completed';
				
				tasklist.add(obtask);
		
		
		
	}
	
}

insert tasklist;

insert feedpost;

 Since your original insert was on a list of objects, you can use the position in the SaveResult list to get the info from the original object that was just inserted.

All Answers

davidjgriffdavidjgriff
Sounds like something in the trigger is going awry. Can you post the actual trigger code?
mxalix258mxalix258

Here is the apex that is invoked from the trigger (this may be written in a horribly inefficient manner, but I'm just learning).

 

//Iterate through the save results
for(Database.SaveResult sr:srl){
    Id obrecord = sr.getid ();
    if(obrecord != null){
            On_Off_Boarding__c postrecord = [SELECT ID, Associated_Application__c, Name FROM On_Off_Boarding__c WHERE id=:obrecord LIMIT 1 ];
                    //creates the new feed post
                    FeedItem post = new FeedItem ();
                    post.ParentId = postrecord.Associated_Application__c;
                    post.Body = 'The onboarding record for ' + postrecord.name + ' has been created';
                    post.LinkUrl = URL.getSalesforceBaseUrl().toExternalForm() + '/' + obrecord;
                    post.Title = 'Onboarding Record';
                    
                    feedpost.add(post);
                    
                    Task obtask = new Task ();
                    obtask.WhatId = postrecord.Associated_Application__c;
                    obtask.OwnerId = UserInfo.getUserId();
                    obtask.Subject = 'Onboarding record created';
                    obtask.status = 'Completed';
                    
                    tasklist.add(obtask);
            
            insert tasklist;
            insert feedpost;
            
             }
        }
}
}

 

davidjgriffdavidjgriff

Well that's one I haven't seen before.

 

You have your insert statement inside your for loop (BAD) so the first time through the loop, you have add a record to the list then insert the list. The second time through, you still have that first record in your list (which now has an Id), add another record, attempt to insert the list and it fails because of that first record.

 

You need to remove the DML statements from your for loop. While you're at it, the SOQL statement should also not exist within a loop. You'll run into governor limits during bulk operations.

mxalix258mxalix258

Ok, I understand what you mean. We are talking about the later half of the code (where it inserts a chatter post and task right?). How do you go about iterating through the saveresult list, and creating a task for each record (without doing a soql query within the for loop?)

 

Thank you!

davidjgriffdavidjgriff

Something like this should do it. (Forgive any typos or compile errors as I have not tested/compiled this code)

 

//Iterate through the save results
for(Integer i = 0;i<srl.size();i++){
	
	Database.SaveResult sr = srl[i];
	
    if(sr.isSuccess()){
		On_Off_Boarding__c postrecord = obrecordToInsert[i];
				//creates the new feed post
				FeedItem post = new FeedItem ();
				post.ParentId = postrecord.Associated_Application__c;
				post.Body = 'The onboarding record for ' + postrecord.name + ' has been created';
				post.LinkUrl = URL.getSalesforceBaseUrl().toExternalForm() + '/' + postrecord.Id;
				post.Title = 'Onboarding Record';
				
				feedpost.add(post);
				
				Task obtask = new Task ();
				obtask.WhatId = postrecord.Associated_Application__c;
				obtask.OwnerId = UserInfo.getUserId();
				obtask.Subject = 'Onboarding record created';
				obtask.status = 'Completed';
				
				tasklist.add(obtask);
		
		
		
	}
	
}

insert tasklist;

insert feedpost;

 Since your original insert was on a list of objects, you can use the position in the SaveResult list to get the info from the original object that was just inserted.

This was selected as the best answer
mxalix258mxalix258
Thank you!