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
ckellieckellie 

How do I update a related record with a map?

I currently am updating a custom object's strategic industry based on the user choosing the industry segment, then apex code is looking up the coorrelating strategic industry. Below is the code

Map<string, Industry_Definition__c> imap = new Map<string, Industry_Definition__c>();
   
    for(Industry_Definition__c i : [select id, Market_Segment__c, Strategic_Industry__c from Industry_Definition__c]){
        imap.put(i.Market_Segment__c, i);
        system.debug('##########i.Market_segment__c:'+ i.market_segment__c);
    }
                     
     for( Integer i = 0; i < Trigger.new.size(); i++){
            trigger.new[i].Strategic_Industry__c = imap.get(trigger.new[i].industry_Segment__c).Strategic_Industry__c;
    }

I need to extend thefunctionality to populate the strategic industry on the related account with the same value as the strategic industry on the trigger.new record. I am trying to use the code below to update the account strategic industry
Map<id, Customer_Product_Line_Item__c> cmap = new Map<id, Customer_Product_Line_Item__c>(Trigger.new);
   
    Account[] relatedaccount = new List<Account>(); relatedaccount = [select id, Strategic_Industry__c from account
        where id in:cmap.keyset()];

    for(Account a : relatedaccount){
        a.Strategic_Industry__c = imap.get(cmap.industry_segment__c).Strategic_Industry__c;
    }

The above code is returning the following error:
Error: Compile Error: Initial term of field expression must be a concrete SObject: MAP<Id,Customer_Product_Line_Item__c> at line 20 column 44


Here is the entire trigger:
trigger IndustrytoAcctOpp on Customer_Product_Line_Item__c (Before Insert, Before Update) {

    Map<string, Industry_Definition__c> imap = new Map<string, Industry_Definition__c>();
   
    for(Industry_Definition__c i : [select id, Market_Segment__c, Strategic_Industry__c from Industry_Definition__c]){
        imap.put(i.Market_Segment__c, i);
        system.debug('##########i.Market_segment__c:'+ i.market_segment__c);
    }
                     
     for( Integer i = 0; i < Trigger.new.size(); i++){
            trigger.new[i].Strategic_Industry__c = imap.get(trigger.new[i].industry_Segment__c).Strategic_Industry__c;
    }
   
    Map<id, Customer_Product_Line_Item__c> cmap = new Map<id, Customer_Product_Line_Item__c>(Trigger.new);
   
    Account[] relatedaccount = new List<Account>(); relatedaccount = [select id, Strategic_Industry__c from account
        where id in:cmap.keyset()];

    for(Account a : relatedaccount){
        a.Strategic_Industry__c = imap.get(cmap.industry_segment__c).Strategic_Industry__c;
    }

}

How do I solve this problem?
Thank you
Best Answer chosen by ckellie
GlynAGlynA
<pre>
trigger IndustrytoAcctOpp on Customer_Product_Line_Item__c ( before insert, before update )
{
    Map<String,String> imap = new Map<String,String>();

    for ( Industry_Definition__c i :
        [   SELECT  Id, Market_Segment__c, Strategic_Industry__c
            FROM    Industry_Definition__c
        ]
        )
    {
        imap.put( i.Market_Segment__c, i.Strategic_Industry__c );
    }

    Map<Id,Customer_Product_Line_Item__c> map_AccountID_CPLI =
        new Map<Id,Customer_Product_Line_Item__c>();

    for ( Customer_Product_Line_Item__c cpli : trigger.new )
    {
        cpli.Strategic_Industry__c = imap.get( cpli.Industry_Segment__c );
        map_AccountID_CPLI.put( cpli.Account__c, cpli );
    }

    List<Account> list_AccountsToUpdate = new List<Account>();
    for ( Account a :
        [   SELECT  Id, Strategic_Industry__c
            FROM    Account
            WHERE   Id IN :map_AccountID_CPLI.keySet()
        ]
        )
    {
        a.Strategic_Industry__c = map_AccountID_CPLI.get( a.Id ).Strategic_Industry__c;
        list_AccountsToUpdate.add( a );
    }
    update list_AccountsToUpdate;
}
</pre>

All Answers

Ashish_SFDCAshish_SFDC
Hi Kellie, 

The dot notation to access a field can only be used on an sObject (you can access static / instance variables using Class / Object names too)

The map you have defined 'LeadMap', is a set of <key, value> pairs where the key is an ID and the value is a Lead.  Your code "LeadMap.get(LeadMap.Assigned__Date__c)" is asking to get the value of an item with the key 'LeadMap.Assigned__Date__c'. 

See the links below, 

http://salesforce.stackexchange.com/questions/13638/getting-an-initial-term-of-field-expression-must-be-a-concrete-sobject-error

https://developer.salesforce.com/forums/ForumsMain?id=906F00000008rXYIAY

Regards,
Ashish

Sonam_SFDCSonam_SFDC
When you are asisgning a value to cmap:
Map<id, Customer_Product_Line_Item__c> cmap = new Map<id, Customer_Product_Line_Item__c>(Trigger.new);

Trigger.new will not be giving the ID and Field pair to the MAP you have created - I understand this is the reason you are getting this error.

Instead you should use something similar to the below usage to get the values assigned to map:

Map<id, Customer_Product_Line_Item__c> cmap  = new Map<id, Customer_Product_Line_Item__c>([Select Id, Customer_Product_Line_Item__c From XXX where ID: Trigger.new.ID]);
GlynAGlynA
@ckellie,

The error is caused by this line:

a.Strategic_Industry__c = imap.get(cmap.industry_segment__c).Strategic_Industry__c;

"cmap" is a map, so you need to use "cmap.get( ... ).industry_segment__c".  The tricky part is: What goes inside the get?

There are few other potential problems with the code:

The query of Industry_Definition__c get all the records of that object.  This could be optimized to get only the records you will need based on the Customer_Product_Line_Item__c records in the trigger.  But, if the total number of Industry_Definition__c records is small, it's probably more efficient to leave it the way it is.

I assume that Customer_Product_Line_Item__c has a lookup field to the Account.  This means that there could be more than one Customer_Product_Line_Item__c record per Account.  If there are, which Strategic_Industry__c value should the Account get?

In your query of the Accounts, you have "where id in:cmap.keyset()".  But the keyset of "cmap" contains Customer_Product_Line_Item__c IDs, not Account IDs, so the query will always return 0 records.  You need to create a set of Account IDs using the lookup from the Customer_Product_Line_Item__c records.

Since you're running in a "before" trigger, you don't have to update the Customer_Product_Line_Item__c records, but you will have to update the Account records.  You don't have an "update" statement for the Accounts that you modify.

The code in the following post is my refactor of your original code.  It assumes (on line 20) that the field that looks up to Account is called "Account__c".  Please change this if necessary.  This code doesn't solve the problem of "which Strategic_Industry__c value should the Account get?"  And I apologize for any typos - I wasn't able to compile the code.

Glyn Anderson
Sr Developer | System Analyst | ClosedWon | closedwon.com
Certified Developer | Certified Advanced Administrator
Blog: GlynATheApexGuy.blogspot.com
Twitter: @GlynAtClosedWon
GlynAGlynA
<pre>
trigger IndustrytoAcctOpp on Customer_Product_Line_Item__c ( before insert, before update )
{
    Map<String,String> imap = new Map<String,String>();

    for ( Industry_Definition__c i :
        [   SELECT  Id, Market_Segment__c, Strategic_Industry__c
            FROM    Industry_Definition__c
        ]
        )
    {
        imap.put( i.Market_Segment__c, i.Strategic_Industry__c );
    }

    Map<Id,Customer_Product_Line_Item__c> map_AccountID_CPLI =
        new Map<Id,Customer_Product_Line_Item__c>();

    for ( Customer_Product_Line_Item__c cpli : trigger.new )
    {
        cpli.Strategic_Industry__c = imap.get( cpli.Industry_Segment__c );
        map_AccountID_CPLI.put( cpli.Account__c, cpli );
    }

    List<Account> list_AccountsToUpdate = new List<Account>();
    for ( Account a :
        [   SELECT  Id, Strategic_Industry__c
            FROM    Account
            WHERE   Id IN :map_AccountID_CPLI.keySet()
        ]
        )
    {
        a.Strategic_Industry__c = map_AccountID_CPLI.get( a.Id ).Strategic_Industry__c;
        list_AccountsToUpdate.add( a );
    }
    update list_AccountsToUpdate;
}
</pre>
This was selected as the best answer
ckellieckellie
Thank you very much GlynA.
GlynAGlynA
You are very welcome.  I'm glad the code helped.

-Glyn