4

I need to retrieve the CreatedDate of the last record creates of every custom object. But the only way I find to do it is by doing a dynamic query in a For or loop. But I’m, of course, limited to 100 custom objects. Did anyone have a solution to avoid the query in the loop ? Or any other workaround ? Thanks

I give you a sample of my code :

public void  method() {
    List<ObjectBuilder__c> listOfRecord = new List<ObjectBuilder__c> () ;       
    for(Schema.SObjectType objTyp : Schema.getGlobalDescribe().Values())
    {
        ObjectBuilder__c oneRecord = new ObjectBuilder__c ()  ; 
        Schema.DescribeSObjectResult describeSObjectResultObj = objTyp.getDescribe();
        objectName = objTyp.getDescribe().getLabel() ; 

        if(describeSObjectResultObj.isCustom() ) {
            if(!name.containsignorecase('history') && !name.containsignorecase('tag')&&
             !name.containsignorecase('share') && !name.containsignorecase('feed') ) {
                oneRecord.Api_Name__c = objTyp.getDescribe().getName(); ; 
                List<sObject> tmp = Database.query('SELECT CreatedDate  FROM '+ oneRecord.Api_Name__c +' order by CreatedDate  desc limit 1 ');
                System.debug('tmp list '+tmp);
                for(sObject obj :tmp ) {
                    oneRecord.Last_Used_Date__c =Date.valueOf(obj.get('CreatedDate')) ; 
                    listOfRecord.add(oneRecord) ;              
                }                      
             }
        }

    }

    INSERT listOfRecord ;

} `
2
  • What are you trying to do? – Raul Mar 22 '17 at 20:22
  • I'm trying to store the last time a record was created in every custom object. With that information I can make a report and know which object is used or not for the last 3/6/9/12 months.. – SF Dev Mar 22 '17 at 20:30
6

Each type of record does have to be queried separately so using a batchable to break up the work into less than 100 types per transaction is how I would approach this:

public class MyBatchable implements Database.Batchable<String> {

    public static void executeAsync() {
        Database.executeBatch(new MyBatchable(), 50);
    }

    public  String[] start(Database.BatchableContext bc) {
        // Return all the types (hundreds)
        String[] types = ...;
        return types;
    }

    public void execute(Database.BatchableContext bc, String[] scope) {
        ObjectBuilder__c[] records = new ObjectBuilder__c[] {};
        // Query the scope types (less than 100)
        insert records;
    }

    public void finish(Database.BatchableContext bc) {
    }
}

then:

MyBatchable.executeAsync();
2
  • Ha. Great minds, I guess. Asynchronous query limit is 200, though. Might as well use the greatest available value. – Adrian Larson Mar 22 '17 at 20:36
  • @AdrianLarson Yep good point. – Keith C Mar 22 '17 at 22:30
4

You could use a batch to get this sort of information. Something like:

public class DemoBatch implements Database.Batchable<SObjectType>
{
    public List<SObjectType> start(Database.BatchableContext context)
    {
        return Schema.getGlobalDescribe().values();
    }
    public void execute(Database.BatchableContext context, List<SObjectType> types)
    {
        List<MyObject__c> records = new List<MyObject__c>();
        for (SObjectType type : types)
        {
            Datetime createdDate = getMostRecentCreatedDate(type);
            if (createdDate != null) records.add(new MyObject__c(
                Api_Name__c = String.valueOf(type),
                Last_Created_Date__c = createdDate
            ));
        }
        insert records;
    }
    public void finish(Database.BatchableContext context) { }

    public static Datetime getMostRecentCreatedDate(SObjectType type)
    {
        try
        {
            List<SObject> records = Database.query(
                'SELECT CreatedDate FROM ' + type + ' ORDER BY CreatedDate DESC LIMIT 1'
            );
            return records.isEmpty() ? null : (Datetime)records[0].get('CreatedDate');
        }
        catch (QueryException q) { return null; }
    }
}

Then execute it with a batch size that will not exceed your governor limits:

Database.execute(new DemoBatch()); // limit is 200 in the asynchronous context

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.