0

Due to a platform limitation that trigger on attachment won't be invoked when an attachment is sent via email I wrote a batch class to clone and parent email attachments from EmailMessage to a custom object Comm__c

global class BatchforOutboundEmailAttachments implements Database.Batchable<sObject>, Schedulable {    

    global Database.QueryLocator start(Database.BatchableContext bc){

        return Database.getQueryLocator([SELECT Name, Body, ParentID from Attachment Where Parent.Type = 'EmailMessage']);    
    }    

    global void execute(Database.BatchableContext bc, Attachment[] scope){

        set<id> parents = new set<id>();
        List<Attachment> newFiles = new List<Attachment>();
        Map<Id,EmailMessage> emailMap = new Map<Id,EmailMessage>();
        List<Attachment> oldFiles = new List<Attachment>();    

            for(Attachment att : scope){
                parents.add(att.ParentID);
            }

            if(!parents.isEmpty()){

       emailMap = new Map<ID, EmailMessage>([SELECT RelatedToId FROM EmailMessage WHERE Id in :Parents]); 

            for (Attachment att : scope) {
              if(emailMap.get(att.ParentId) != Null && emailMap.get(att.ParentId).RelatedToId != NULL){
                if (emailMap.get(att.ParentId).RelatedToId.getSObjectType() == Comm__c.SObjectType) {

                    Attachment newFile = att.clone();
                    newFile.ParentId = emailMap.get(att.ParentId).RelatedToId;
                    newFiles.add(newFile);
                    oldFiles.add(att);

                }
             }
            }     


       try{
            insert newFiles;
            delete oldFiles;
          }

           catch(DMLexception de){}    
        }

    }

    global void finish(Database.BatchableContext bc){
     }

    global void execute(SchedulableContext sc){

         ID jobId = Database.executeBatch(this,100); 

        }
}

In the start method I'm receiving 12k attachments which are EmailMessage records but not related to Comm__c i.e.( RelatedToID is not of SobjectType Comm__c)

How can I reduce the scope size so that less number of batches are processed? Someone from the client team doesn't want the unrelated attachments to be returned in the scope

1

The type of the parent object can be included as a filter as described in How to filter query for specific types of parent lookup? and you are already doing that.

But you are also asking for the SOQL query engine to accept your coded logic that the parent object type is of EmailMessage so that a RelatedToId can also be assumed. In code you might be able to inform the compiler using a cast, but AFAIK no such mechanism exists in SOQL.

So I don't think you can filter further in the SOQL and so will need to stick to the Apex filtering.

4
  • Are you suggesting Apex filtering in a class which implements Iterator<Attachment> ? – Jarvis Sep 10 '18 at 14:51
  • @Bennie No, because if you don't use a QueryLocator you are back from 50,000,000 rows to normal governor limits. I'm suggesting use your present code - let the machine do the hard work. Or if there is a specific problem you have with that, include that problem in your question. – Keith C Sep 10 '18 at 14:53
  • Someone from the client team doesn't want the unrelated attachments to be returned in the scope – Jarvis Sep 10 '18 at 15:21
  • 1
    @Bennie Suggest you let them know that there is no safe, simple way to do that as far as you know so trying to do it adds cost/risk/complication. If they can argue why those costs are justified then that is one thing, but if it is just an opinion then you are done - leave it as is (assuming it has been tested and works). – Keith C Sep 10 '18 at 15:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.