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
Andrew Hoban 6Andrew Hoban 6 

Calling @Future Class Method From Trigger

HI,

I have a trigger on Cases that populates the Contact lookup field by using two fields (Concat_Id__c) in each object as a reference. The logic for this works, however as we have thousands of contact records, I am getting the error message: Non-selective query against large object type (more than 200000 rows)

I have read that using a @future class is a good workaround but have never come across them before.

Woud anyone be able to show me how to use this with my trigger?

Trigger:
trigger UpdateContact on Case (before update) {

for (Case createdCase : Trigger.New) {
            if(createdCase.SuppliedEmail!=null) {
            Case[] Cases = [Select Id,concat_ID__c,SuppliedEmail from Case where SuppliedEmail != Null];
           
                //look for a Contact that matches the email address
                Account[] AccountsMatched = [Select Id,concat_ID__c,PersonEmail, Name from Account where concat_ID__c =:createdCase.concat_ID__c  LIMIT 1];
                //if we found a match, use it
                if (AccountsMatched.size()>0) {
                    createdCase.Contactid = AccountsMatched[0].Id;
                
               }
               
          }
     }
  }

 
Chris  ByromChris Byrom
I don't think calling an asynchronous method is going to help you here. Your query must be "selective". Check out the "More Efficient SOQL Queries" section of this article to help get your query under control. :)

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_SOQL_VLSQ.htm

You also are going to want to get your SOQL queries out of the for loop. This is a no no for Apex coding, as you can easily run into governor limits with the number of queries being executed. This article teaches you how to bulkify your trigger, so that you only have to make one call to the database to get all the data you need.

http://www.sfdc99.com/2014/01/18/bulkifying-code/

I would reccomend checking out the entire bulkify your code series there. It is to me, the primary challenge to understand when coding for SF.
Andrew Hoban 6Andrew Hoban 6
Thank you for this information. I will look over this document. The issue im going to face is that there are over 700,000 contact records that it needs to look over, and this is after trying to filter it down!
Chris  ByromChris Byrom
That is never going to work unfortunately. The query size is way to big. You need to only work on the cases that are currently being modified in your trigger.
 
Case[] Cases = [Select Id,concat_ID__c,SuppliedEmail from Case where SuppliedEmail != Null];

This line here is blowing up the scope of what you are trying to operate on. It is saying give me every case in the database without a SuppliedEmail. Triggers aren't meant to do this sort of thing. They are meant to operate on up to 200 records that are currently being modified by the system. It looks like this query is not needed at all in your trigger however as you aren't referencing this list at all in it.

Next what is Concat_ID__c? It appears you should also limit your account query to the list of emails that the cases you are working have. You are trying to find the person account for the email supplied in the case right? If so, you should limit your account query to accounts that match that email address.
 
Andrew Hoban 6Andrew Hoban 6
Hi Chris,

That line is redundant and needs to be removed from the trigger. Sorry for the confusion!

This trigger is working on the current case that is being updated. The lookup to Contact is the object that has the thousands of records. 

Concat_ID__c is a formula field that combines SuppliedName and Supplied email together. I have the same field replicated on Account called the same thing. Basically im trying to create a unique id for the lookup on the trigger. 

My problem is trying to filter the Account query to get under 200,000 records, however there are around 400,000 we need to look across to populate the lookup.

Do you think there is anyway to query this many records?

Thanks for the help!
Andrew Hoban 6Andrew Hoban 6
Also, I have contacted Salesforce to allow the formula field to be indexed. We are using Person Accounts on our org hence why I mention Accounts under Contacts.
Chris  ByromChris Byrom
If you get an index created that should correct your problem, if the query is too slow. This should be a selective query I believe, as you should not have the same entry multiple times on more than one Account. If it doesn't work, you might think about creating a Text field to store the values and make it Unique. This would make it so that any time an Account is created users won't be allowed to create duplicates. You could populate the field with a Workflow, Trigger, etc. Then get an index put on it, and the queries should work. You currently have a risk of having multiple identical accounts being returned for each Concat_ID__c.