+ Start a Discussion
neckrneckr 

Save Function not Updating Child Objects but saves fine

Hi, I am trying to display and update fields for an my License_Verification__c Object 
with a lookup with Contacts.  I want to update and save in one shot, however my 
contact fields are not being updated on Save and not sure what I am missing, please help.
public with sharing class ConAcctVerificationInfoControllerExt {
   
    
private ApexPages.StandardController std;           

// Associated Licenses
public List<License_Verification__c> licenses;

// License Agency Contact
Contact LicenseAgencyContact;

public ConAcctVerificationInfoControllerExt(ApexPages.StandardController stdCtrl)
    {      
    std=stdCtrl;     
    }           
    
    public Account getAccount()     
    {      
        return (Account) std.getRecord();    
    }    
     

//----------------------------LICENSES METHOD--------------------------------------->
     
      public List<License_Verification__c> getlicenses()     
       {        
         if ( (null!=getAccount().id) && (licenses == null) )
              
       {            
        licenses=[SELECT Id, Account__r.ID, Account__c, LV_Agency_Contact__r.ID, LV_Agency_Contact__r.Company_Name__c,LV_Agency_Contact__r.Email, LV_Agency_Contact__r.Phone, LV_Agency_Contact__r.LastName,LV_Agency_Contact__r.FirstName, LV_Agency_Contact__r.Fax, LV_License_Type__c, LV_License_Number__c,LV_License_Expiration_Date__c                          
        FROM License_Verification__c                           
        WHERE Account__c = : getAccount().ID                          
        ORDER BY CreatedDate];
                       }                                    
        return licenses;   
       }       
     
public PageReference save()     
  {      
  Boolean result=true;      
  PageReference pr=Page.TestParentChild;      
  if (null!=getAccount().id)      
  {       
  result=updateContacts();     
   }      
    else     
  {       
   pr.setRedirect(true);      
  }             
  if (result)      
  {         
// call standard controller save, but don't capture the return value which will redirect to view page         
  update Principalcontact;
  update IDV;
  update licenses; // ONLY FIELDS ON PARENT OBJECT ARE BEING UPDATED ON SAVE                                                
   std.save();            
 ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'Changes saved'));      
 }         
pr.getParameters().put('id', getAccount().id);             
 return pr;     
 }  

 

 

<apex:page standardController="Account" extensions="ConAcctVerificationInfoControllerExt" title="Test Verification Info" >

<apex:pageMessages />     
<apex:form >         

<apex:pageBlock mode="mainDetail">             
<apex:pageBlockButtons location="top">                 
<apex:commandButton action="{!cancel}" value="Exit" />                 
<apex:commandButton action="{!save}" value="Save" />                 
</apex:pageBlockButtons> 

            
<apex:repeat value="{!licenses}" var="license" >                     

<apex:pageBlockSection columns="2"  title="License {!license.LV_License_Type__c}:{!license.LV_License_Number__c} Verification" collapsible="true">                         
                
<!--<apex:repeat value="{!$ObjectType.License_Verification__c.FieldSets.LV_Input_Info}" var="field">                      
<apex:inputField value="{!license[field]}" />                     
</apex:repeat>--> 
<apex:inputfield value="{!license.LV_Agency_Contact__r.ID}" /> 
<apex:inputfield value="{!license.Account__r.ID}" />
<apex:inputfield value="{!license.LV_License_Type__c}"/>
<apex:inputField value="{!license.LV_Agency_Contact__r.FirstName}" />
<apex:inputfield value="{!license.LV_License_Number__c}"/>
<apex:inputField value="{!license.LV_Agency_Contact__r.LastName}" />  
<apex:inputfield value="{!license.LV_License_Expiration_Date__c}"/>
<apex:inputField value="{!license.LV_Agency_Contact__r.Email}" />
<apex:inputfield value="{!license.LV_Agency_Contact__r.Company_Name__c}"/>
<apex:inputField value="{!license.LV_Agency_Contact__r.Phone}" />                       

<div style="text-align:center">                            
<apex:commandButton action="{!save}" value="Save" />
<!--<apex:commandButton action="{!AddNewLicense}" value="Add New" /> -->                            
</div>     
                                           
</apex:pageBlockSection>                        
               
</apex:repeat>             

 

Best Answer chosen by Admin (Salesforce Developers) 
ColinKenworthyColinKenworthy

My bad...

 

public List<Contact> LicenseAgencyContact;

 

 

LicenseAgencyContact = new List<Contact>(); // initialise if not already done so

for (License_Verification__c lic : licenses) {

        LicenseAgencyContact.add( lic.LV_Agency_Contact__r );

}


All Answers

bob_buzzardbob_buzzard

So if I understand correctly, your licenses get updated, but not the values that have been applied to the related LV agency contact?

 

I'm pretty sure you can't do this - I'm sure I've read that Apex won't traverse the object graph, probably something to do with the fact that your update would be affecting sobjects of multiple different types.  I'll try to find the doc that I read this in.

bob_buzzardbob_buzzard

This is what the Apex developer's guide has to say. Its related to upsert, but specifically talks about updates and there's a similar entry for the insert method:

 

--- snip ---

 

 

The upsert statement can only set the ID of related sObject records. Fields on related records cannot be modified with
upsert. For example, if updating an existing contact, you can specify the contact's related account record by setting the
value of the AccountId field. However, you cannot change the account's name without updating the account itself with
a separate DML statement.

 

--- snip ---

ColinKenworthyColinKenworthy

You'll need to create a variable in your class to store the LV_Agency_Contact__c and do a seperate update on it.

neckrneckr

Ok. Thanks for the help.

 

In terms of your suggestion to create a new class variable, I created

 

public List<Contact> LicenseAgencyContact;

 

However not sure how I would assign the query list results of <License_Verification__c> to <Contact> type within my class.

 

Thinking along these lines, but didn't fly. 

 

LicenseAgencyContact = licenses.LV_Agency_Contact__r;

Do I need to run a seperate query to populate the <Contact> List.   I was initially going in this direction and got stumped with mapping the two lists together, so looked for what I thought would be a simplier solution.  A code example would help me understand your suggestion a bit better.

Thanks,


Ricky

ColinKenworthyColinKenworthy

for (License_Verification__c lic : licenses) {

    for (Contact con : lic.LV_Agency_Contact__r) {

        LicenseAgencyContact = con;

    }

}


might work, and there is only one licence and contact.

neckrneckr

There is a one to one relationship between license and contact however there can be multiple liceneses.

 

I tried putting the code within the  public List<License_Verification__c> getlicenses() method and I receieve this error.

 

Illegal assignment from SOBJECT:Contact to LIST<Contact>

 

It appears that  this line lic.LV_Agency_Contact__r is not reading as a Contact Object.


Is there something else I am missing?

ColinKenworthyColinKenworthy

Ah I think its down to List of objects vs. object. Would this work? Changing the variable to a single object.

 

LicenseAgencyContact = licenses.LV_Agency_Contact__r;  << doesn't work since licences is a List rather than a single License_Verification__c object.

 


try this? Make a variable of type Contact.

 

public Contact LicenseAgencyContact;


for (License_Verification__c lic : licenses) {

    LicenseAgencyContact = lic.LV_Agency_Contact__r;

}

 


neckrneckr

The syntax your provided works however since LicenseAgencyContact is no longer a list it wouldn't store and save all contacts and I tested it with two Liscneses and two contacts and it only saves the changes to the 2nd Contact.

So I guess I would have to go back to your fist code suggestion and iterate over the licenses and assign them to LicenseAgencyContact.  Not sure where to begin with the syntax, can you provide an example or do you see the solution differently?

 

 

I'm thinking someting like this?

 

 

public List<Contact> LicenseAgencyContact;

 

//int i=0;

for (License_Verification__c lic : licenses[i]) { // add int i =0; i++;

    for (Contact con : lic.LV_Agency_Contact__r) {

        LicenseAgencyContact = con;

    }

}

ColinKenworthyColinKenworthy

OK, if we go back to a List of Contacts then I think

 

public List<Contact> LicenseAgencyContact;

 

 

LicenseAgencyContact = new List<Contact>(); // initialise if not already done so

for (License_Verification__c lic : licenses) {

    for (Contact con : lic.LV_Agency_Contact__r) {

        LicenseAgencyContact.add(con);

    }

}

neckrneckr

Thanks for the syntax help for the list. I get this error for this line for (Contact con : lic.LV_Agency_Contact__r) 

Error: Loop must iterate over a collection type: SOBJECT:Contact

Looks like same issue as before not reading licenses.LV_Agency_Contact__r as a Contact Object.  Any ideas?

ColinKenworthyColinKenworthy

My bad...

 

public List<Contact> LicenseAgencyContact;

 

 

LicenseAgencyContact = new List<Contact>(); // initialise if not already done so

for (License_Verification__c lic : licenses) {

        LicenseAgencyContact.add( lic.LV_Agency_Contact__r );

}


This was selected as the best answer
neckrneckr

Perfection! Thanks for your help, much appreciated!

neckrneckr

I have a delete License Method where I am trying to delete the License record and associated Contact record in one shot.  It has no problem deleting the License record but gives me an error when trying to delete the Contact record associated. 

 

System.ListException: Missing id at index: 0

 

Is there something I am missing when capturing the contact Id for the delete function?  I am a bit stuck on what I can possibly do next, pleas help. Here is my method:

 

public void deleteLicense()     
{        
          
if (null!=chosenLicenseId)           
{              
License_Verification__c LV = new License_Verification__c(Id=chosenLicenseId);   

chosenLicenseAgencyContactId = LV.LV_Agency_Contact__r.id;            

Contact LVAgencyCont = new Contact(Id = chosenLicenseAgencyContactId);

delete LV;
delete LVAgencyCont;                        

LV=null;
LVAgencyCont = null;            
chosenLicenseId=null;
chosenLicenseAgencyContactId=null;           
}        
    
} 

 

ColinKenworthyColinKenworthy

Does this line actually work?

chosenLicenseAgencyContactId = LV.LV_Agency_Contact__r.id;

 

Assuming you have your list of licenses variable still populated, I would loop through it and pull out the licence matching the licence number; it would have all the object relationships and values in it so you should be able to ge the right contact or contact id.