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
neckrneckr 

Trigger not assigning Account ID

Hi, First time working with a trigger and it is not assigning the Account ID from ST.Account__r.Id,  is there something I am missing?

 

trigger ConVerificationRecordSetup on Con_Service_Task_Request__c (after insert, after update) 
{

for (Con_Service_Task_Request__c ST : Trigger.new) {

if (!ST.Service__r.Bankruptcy_Judgements_Liens_Report__c) { 

Contact BJLVAgencyContact = new Contact(AccountId = ST.Account__r.Id , Contact_Type__c = 'BJLV Agency', LastName = 'Agency Contact');
insert BJLVAgencyContact;
 
Bankruptcy_Judgements_Liens_Report__c BJLV = new Bankruptcy_Judgements_Liens_Report__c(Account__c = ST.Account__r.Id , BJLV_Agency_Contact__c = BJLVAgencyContact.ID );    
insert BJLV;      

}
}

}

 

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

Don't use __r relationships unless you have queried them. They will not work, because of the "lazy query" optimization of triggers.

 

Just use ST.Account__c instead.

 

Edit: Clarification... only field values that were directly involved in record will be available without a query.

 

An example of what won't work:

 

 

trigger lazyDatabaseViolation on Contact ( before insert, before update ) {
  for(Contact c:Trigger.new) {
c.Test_Contact__c = c.Account.Test_Account__c; // WRONG: We have not queried Account.
} }

Assuming Test_Account__c and Test_Contact__c are valid checkbox fields, this code will save without complaining. However, when you try to execute it, it will cause an exception, because Contact.Account has not been queried.

 

To use relationships, either children or parent, you have to query them first:

 

 

trigger lazyDatabaseViolation on Contact ( before insert, before update ) {
  Map<Id,Account> accounts = new Map<Id,Account>();
  for(Contact c:Trigger.new)
    accounts.put(c.accountid,null);
  accounts = new map<id,account>([select id,test_account__c from account where id in :accounts.keyset()]);
  for(Contact c:Trigger.new)
    if(accounts.get(c.accountid)<>null)
      c.test_contact__c = accounts.get(c.accountid).test_account__c;
}

Does this help?

 

 

All Answers

Rahul S.ax961Rahul S.ax961

Here, Account is standard field.

so change  'ST.Account__r.Id' to 'ST.Account.Id'.

__r is used for Custom objects.

neckrneckr

Account is a lookupfield on my Con_Service_Task_Request__c custom object.

 

I trried your suggestion and it will gives me the following error.

 

Compile Error: Invalid foreign key relationship: Con_Service_Task_Request__c.Account

 

Any other thoughts or suggestions?

sfdcfoxsfdcfox

Don't use __r relationships unless you have queried them. They will not work, because of the "lazy query" optimization of triggers.

 

Just use ST.Account__c instead.

 

Edit: Clarification... only field values that were directly involved in record will be available without a query.

 

An example of what won't work:

 

 

trigger lazyDatabaseViolation on Contact ( before insert, before update ) {
  for(Contact c:Trigger.new) {
c.Test_Contact__c = c.Account.Test_Account__c; // WRONG: We have not queried Account.
} }

Assuming Test_Account__c and Test_Contact__c are valid checkbox fields, this code will save without complaining. However, when you try to execute it, it will cause an exception, because Contact.Account has not been queried.

 

To use relationships, either children or parent, you have to query them first:

 

 

trigger lazyDatabaseViolation on Contact ( before insert, before update ) {
  Map<Id,Account> accounts = new Map<Id,Account>();
  for(Contact c:Trigger.new)
    accounts.put(c.accountid,null);
  accounts = new map<id,account>([select id,test_account__c from account where id in :accounts.keyset()]);
  for(Contact c:Trigger.new)
    if(accounts.get(c.accountid)<>null)
      c.test_contact__c = accounts.get(c.accountid).test_account__c;
}

Does this help?

 

 

This was selected as the best answer
neckrneckr

In my case, are there any syntax shortcuts I can use in the trigger to check the number  of  records in a custom child object to ST.Account__c?  Something like ST.Account__c.My_Custom_Object__c.Size()

sfdcfoxsfdcfox

You can use List.Size() (as your example), assuming you perform the query you need to populate your data. By the way, your trigger code is not bulk-safe (try running 100 records through the data loader, you'll run into an exception).

 

Assuming you have a query like this:

 

 

Map<Id,list<Account>> records =  new Map<Id,Account>();
for(Account a:[select id,Con_Service_Task_Request__c,(select id from my_custom_object__r) from account where Con_Service_Task_Request__c in :trigger.new]) {
  if(records.get(a.Con_Service_Task_Request__c)==null) {
    records.put(a.Con_Service_Task_Request__c,new List<Account>());
  }
  records.get(a.Con_Service_Task_Request__c).add(a);
}

 

At this point, you have a list of accounts, grouped by the Con_Service_Task_Request__c object; inside each account is a list of My_Custom_Object__c. You can then go through that list; records.get(ST.id)[index].My_Custom_Object__r.Size() is the number of My_Custom_Object__c records in the list.

 

Your trigger needs to be bulkified at some point... See this page: http://wiki.developerforce.com/index.php/Best_Practice:_Bulkify_Your_Code

neckrneckr

Thanks for the gudiance, I spend the entire day trying to get my head around maps as I have not used them before. I think I got the logic behind your suggestion, but having trouble with the syntax.

I tried the suggested code and received the following Error.

Error: No such column 'Con_Service_Task_Request__c' on entity 'Account'

I tried Service_Tasks__r.ID in replacement of Con_Service_Task_Request__c and still doesnt like the relationship syntax.

I doubled checked my schema and confirmed Con_Service_Task_Request__c is a child object of Account and the relationship name is Service_Tasks__r.  Account is a master detail lookup field in Con_Serice_Task_Request, same goes for all my_custom_Object's referenced below.

I have more than one custom object that I need to do this for, and the link on bulkfying my code has me thinking that I should be thinking about building everything in one go from the start. I included my latest code, based on your samples and what I think are neccessary extensions to include more custom objects.

Any suggestions on how to get this to compile?

 

trigger ConVerificationRecordSetup on Con_Service_Task_Request__c (after insert, after update) 
{

Map<Id,List<Account>> records = new Map<Id,Account>();
for(Account a:[SELECT id, Con_Service_Task_Request__c, 
(select id from My_Custom_Object1__r), 
(select id from My_Custom_Object2__r), 
(select id from My_Custom_Object3__r), 
(select id from My_Custom_Object4__r), 
(select id from My_Custom_Object5__r), 
(select id from My_Custom_Object6__r), 
(select id from My_Custom_Object7__r), 
(select id from My_Custom_Object8__r), 
FROM Account 
WHERE Con_Service_Task_Request__c in :trigger.new]) {
    if(records.get(a.Con_Service_Task_Request__c)==null)  {
        records.put(a.Con_Service_Task_Request__c, new List<Account>());
    }
    records.get(a.Con_Service_Task_Request__c).add(a);
}   

for (Con_Service_Task_Request__c ST : Trigger.new) {


if (records.get(ST.id)[index].My_Custom_Object1__r.Size()  == 0 ) { 

 //Insert New Record Code Here     
}

if (records.get(ST.id)[index].My_Custom_Object2__r.Size()  == 0 ) {

 //Insert New Record Code Here   
}
 
if (records.get(ST.id)[index].My_Custom_Object3__r.Size()  == 0 ) {

 //Insert New Record Code Here   

}
// Continue through to My_Custom_Object8__r
 
}