Batch APEX requiring two queries and hitting limits

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
I have a batch APEX class that is used to delete any contacts that have been created over a year ago and have no related opportunities.
I have queries for the contacts in the QueryLocator. I am then querying for all opportunities in the execute however am hitting limits.
Can anyone suggest how I can query all opportunities without errors?
Batch Class
global class DeleteContact implements Database.Batchable<sObject>
global date d = system.today().addYears(-1).addDays(-3);
public String query = 'select id, opportunity__c, RecordTypeId, email, customer_Number__c from contact where createddate <= :d';
global Database.QueryLocator start(Database.BatchableContext BC)
return Database.getQueryLocator(query);
global void execute(Database.BatchableContext BC, List<Contact> scope)
Map<Id, Id> oppMap = new Map<Id, Id>();
Map<Id, Contact> contactMap = new Map<Id, Contact>();
List<Contact> contactsInScope = new List<Contact>();
for(Contact c: scope)
if(!contactMap.containsKey(c.id))
contactMap.put(c.id, c);
List<Opportunity> opportunities = new List<Opportunity>();
opportunities = [select id, contact__c, stagename from opportunity where contact__c != ''];
for(Opportunity o : opportunities)
if(contactMap.containskey(o.Contact__c) )
oppMap.put(o.Contact__c, o.id);
for(Contact con : scope)
if(!oppMap.containsKey(con.id))
contactsInScope.add(con);
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
List<Contact> contactsToDelete = new List<Contact>();
for(Contact co : contactsInScope)
if(co.RecordTypeId == b2cId)
if(co.Customer_Number__c == '')
if(!co.email.contains('@icslearn.co.uk'))
contactsToDelete.add(co);
if(contactsToDelete.size()>0)
try
delete contactsToDelete;
catch(Exception e)
global void finish(Database.BatchableContext BC)
apex batch governorlimits
add a comment |Â
up vote
1
down vote
favorite
I have a batch APEX class that is used to delete any contacts that have been created over a year ago and have no related opportunities.
I have queries for the contacts in the QueryLocator. I am then querying for all opportunities in the execute however am hitting limits.
Can anyone suggest how I can query all opportunities without errors?
Batch Class
global class DeleteContact implements Database.Batchable<sObject>
global date d = system.today().addYears(-1).addDays(-3);
public String query = 'select id, opportunity__c, RecordTypeId, email, customer_Number__c from contact where createddate <= :d';
global Database.QueryLocator start(Database.BatchableContext BC)
return Database.getQueryLocator(query);
global void execute(Database.BatchableContext BC, List<Contact> scope)
Map<Id, Id> oppMap = new Map<Id, Id>();
Map<Id, Contact> contactMap = new Map<Id, Contact>();
List<Contact> contactsInScope = new List<Contact>();
for(Contact c: scope)
if(!contactMap.containsKey(c.id))
contactMap.put(c.id, c);
List<Opportunity> opportunities = new List<Opportunity>();
opportunities = [select id, contact__c, stagename from opportunity where contact__c != ''];
for(Opportunity o : opportunities)
if(contactMap.containskey(o.Contact__c) )
oppMap.put(o.Contact__c, o.id);
for(Contact con : scope)
if(!oppMap.containsKey(con.id))
contactsInScope.add(con);
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
List<Contact> contactsToDelete = new List<Contact>();
for(Contact co : contactsInScope)
if(co.RecordTypeId == b2cId)
if(co.Customer_Number__c == '')
if(!co.email.contains('@icslearn.co.uk'))
contactsToDelete.add(co);
if(contactsToDelete.size()>0)
try
delete contactsToDelete;
catch(Exception e)
global void finish(Database.BatchableContext BC)
apex batch governorlimits
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have a batch APEX class that is used to delete any contacts that have been created over a year ago and have no related opportunities.
I have queries for the contacts in the QueryLocator. I am then querying for all opportunities in the execute however am hitting limits.
Can anyone suggest how I can query all opportunities without errors?
Batch Class
global class DeleteContact implements Database.Batchable<sObject>
global date d = system.today().addYears(-1).addDays(-3);
public String query = 'select id, opportunity__c, RecordTypeId, email, customer_Number__c from contact where createddate <= :d';
global Database.QueryLocator start(Database.BatchableContext BC)
return Database.getQueryLocator(query);
global void execute(Database.BatchableContext BC, List<Contact> scope)
Map<Id, Id> oppMap = new Map<Id, Id>();
Map<Id, Contact> contactMap = new Map<Id, Contact>();
List<Contact> contactsInScope = new List<Contact>();
for(Contact c: scope)
if(!contactMap.containsKey(c.id))
contactMap.put(c.id, c);
List<Opportunity> opportunities = new List<Opportunity>();
opportunities = [select id, contact__c, stagename from opportunity where contact__c != ''];
for(Opportunity o : opportunities)
if(contactMap.containskey(o.Contact__c) )
oppMap.put(o.Contact__c, o.id);
for(Contact con : scope)
if(!oppMap.containsKey(con.id))
contactsInScope.add(con);
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
List<Contact> contactsToDelete = new List<Contact>();
for(Contact co : contactsInScope)
if(co.RecordTypeId == b2cId)
if(co.Customer_Number__c == '')
if(!co.email.contains('@icslearn.co.uk'))
contactsToDelete.add(co);
if(contactsToDelete.size()>0)
try
delete contactsToDelete;
catch(Exception e)
global void finish(Database.BatchableContext BC)
apex batch governorlimits
I have a batch APEX class that is used to delete any contacts that have been created over a year ago and have no related opportunities.
I have queries for the contacts in the QueryLocator. I am then querying for all opportunities in the execute however am hitting limits.
Can anyone suggest how I can query all opportunities without errors?
Batch Class
global class DeleteContact implements Database.Batchable<sObject>
global date d = system.today().addYears(-1).addDays(-3);
public String query = 'select id, opportunity__c, RecordTypeId, email, customer_Number__c from contact where createddate <= :d';
global Database.QueryLocator start(Database.BatchableContext BC)
return Database.getQueryLocator(query);
global void execute(Database.BatchableContext BC, List<Contact> scope)
Map<Id, Id> oppMap = new Map<Id, Id>();
Map<Id, Contact> contactMap = new Map<Id, Contact>();
List<Contact> contactsInScope = new List<Contact>();
for(Contact c: scope)
if(!contactMap.containsKey(c.id))
contactMap.put(c.id, c);
List<Opportunity> opportunities = new List<Opportunity>();
opportunities = [select id, contact__c, stagename from opportunity where contact__c != ''];
for(Opportunity o : opportunities)
if(contactMap.containskey(o.Contact__c) )
oppMap.put(o.Contact__c, o.id);
for(Contact con : scope)
if(!oppMap.containsKey(con.id))
contactsInScope.add(con);
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
List<Contact> contactsToDelete = new List<Contact>();
for(Contact co : contactsInScope)
if(co.RecordTypeId == b2cId)
if(co.Customer_Number__c == '')
if(!co.email.contains('@icslearn.co.uk'))
contactsToDelete.add(co);
if(contactsToDelete.size()>0)
try
delete contactsToDelete;
catch(Exception e)
global void finish(Database.BatchableContext BC)
apex batch governorlimits
apex batch governorlimits
asked 1 hour ago
Hannah
238
238
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
4
down vote
I have few recommendation regarding your code:
- Make query selective.
[select id, contact__c, stagename from opportunity where contact__c != ''];is a bad query - Split large methods into few small methods. Method
executeis too large - Pass as
queryLocatornot justStringof query, but staticSOQLquery. It could prevent from having runtime exceptions to compile exceptions, that are more easy to fix. instead ofDatabase.getQueryLocator('select id from Account');useDatabase.getQueryLocator([select id from Account]); - Catch exceptions only if you know what to do with it, otherwise you will not receive any errors if those occur
try
delete contactsToDelete;
catch(Exception e) // is not a best practice
your code could be re-write to query Contacts, that are not in Contact__c on Opportunities
global class DeleteContact implements Database.Batchable<sObject>
private Date dateToDeleteTo;
global DeleteContact()
dateToDeleteTo = Date.today().addYears(-1).addDays(-3);
global Database.QueryLocator start(Database.BatchableContext BC)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
return Database.getQueryLocator([
select Id
from Contact
where Id not in (
select Contact__c
from Opportunity
where Contact__c != null
)
and RecordTypeId = :b2cId
and Email like '%@icslearn.co.uk'
and CreatedDate <= :dateToDeleteTo
]);
global void execute(Database.BatchableContext BC, List<Contact> scope)
delete scope;
global void finish(Database.BatchableContext BC)
add a comment |Â
up vote
3
down vote
You can easily optimize this code. First query Opportunity as child records instead of querying all opportunity in system. Which will also reduce your line of code.
global class DeleteContact implements Database.Batchable<sObject>
global date d = system.today().addYears(-1).addDays(-3);
//check and verify relationship name
public String query = 'select id, opportunity__c, RecordTypeId, email, customer_Number__c, (SELECT ID FROM Opportunity__r LIMIT 1) from contact where createddate <= :d';
global Database.QueryLocator start(Database.BatchableContext BC)
return Database.getQueryLocator(query);
global void execute(Database.BatchableContext BC, List<Contact> scope)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
List<Contact> contactsToDelete = new List<Contact>();
// just check the child list size . if its 0 then it don't have record and you can proceed to delete
for(Contact co : contactsInScope)
if(co.Opportunity__r.size() == 0 && co.RecordTypeId == b2cId && co.Customer_Number__c == '' && !co.email.contains('@icslearn.co.uk'))
contactsToDelete.add(co);
//As this is Asyn so try catch won't make a difference here and you can remove them
delete contactsToDelete;
global void finish(Database.BatchableContext BC)
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
I have few recommendation regarding your code:
- Make query selective.
[select id, contact__c, stagename from opportunity where contact__c != ''];is a bad query - Split large methods into few small methods. Method
executeis too large - Pass as
queryLocatornot justStringof query, but staticSOQLquery. It could prevent from having runtime exceptions to compile exceptions, that are more easy to fix. instead ofDatabase.getQueryLocator('select id from Account');useDatabase.getQueryLocator([select id from Account]); - Catch exceptions only if you know what to do with it, otherwise you will not receive any errors if those occur
try
delete contactsToDelete;
catch(Exception e) // is not a best practice
your code could be re-write to query Contacts, that are not in Contact__c on Opportunities
global class DeleteContact implements Database.Batchable<sObject>
private Date dateToDeleteTo;
global DeleteContact()
dateToDeleteTo = Date.today().addYears(-1).addDays(-3);
global Database.QueryLocator start(Database.BatchableContext BC)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
return Database.getQueryLocator([
select Id
from Contact
where Id not in (
select Contact__c
from Opportunity
where Contact__c != null
)
and RecordTypeId = :b2cId
and Email like '%@icslearn.co.uk'
and CreatedDate <= :dateToDeleteTo
]);
global void execute(Database.BatchableContext BC, List<Contact> scope)
delete scope;
global void finish(Database.BatchableContext BC)
add a comment |Â
up vote
4
down vote
I have few recommendation regarding your code:
- Make query selective.
[select id, contact__c, stagename from opportunity where contact__c != ''];is a bad query - Split large methods into few small methods. Method
executeis too large - Pass as
queryLocatornot justStringof query, but staticSOQLquery. It could prevent from having runtime exceptions to compile exceptions, that are more easy to fix. instead ofDatabase.getQueryLocator('select id from Account');useDatabase.getQueryLocator([select id from Account]); - Catch exceptions only if you know what to do with it, otherwise you will not receive any errors if those occur
try
delete contactsToDelete;
catch(Exception e) // is not a best practice
your code could be re-write to query Contacts, that are not in Contact__c on Opportunities
global class DeleteContact implements Database.Batchable<sObject>
private Date dateToDeleteTo;
global DeleteContact()
dateToDeleteTo = Date.today().addYears(-1).addDays(-3);
global Database.QueryLocator start(Database.BatchableContext BC)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
return Database.getQueryLocator([
select Id
from Contact
where Id not in (
select Contact__c
from Opportunity
where Contact__c != null
)
and RecordTypeId = :b2cId
and Email like '%@icslearn.co.uk'
and CreatedDate <= :dateToDeleteTo
]);
global void execute(Database.BatchableContext BC, List<Contact> scope)
delete scope;
global void finish(Database.BatchableContext BC)
add a comment |Â
up vote
4
down vote
up vote
4
down vote
I have few recommendation regarding your code:
- Make query selective.
[select id, contact__c, stagename from opportunity where contact__c != ''];is a bad query - Split large methods into few small methods. Method
executeis too large - Pass as
queryLocatornot justStringof query, but staticSOQLquery. It could prevent from having runtime exceptions to compile exceptions, that are more easy to fix. instead ofDatabase.getQueryLocator('select id from Account');useDatabase.getQueryLocator([select id from Account]); - Catch exceptions only if you know what to do with it, otherwise you will not receive any errors if those occur
try
delete contactsToDelete;
catch(Exception e) // is not a best practice
your code could be re-write to query Contacts, that are not in Contact__c on Opportunities
global class DeleteContact implements Database.Batchable<sObject>
private Date dateToDeleteTo;
global DeleteContact()
dateToDeleteTo = Date.today().addYears(-1).addDays(-3);
global Database.QueryLocator start(Database.BatchableContext BC)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
return Database.getQueryLocator([
select Id
from Contact
where Id not in (
select Contact__c
from Opportunity
where Contact__c != null
)
and RecordTypeId = :b2cId
and Email like '%@icslearn.co.uk'
and CreatedDate <= :dateToDeleteTo
]);
global void execute(Database.BatchableContext BC, List<Contact> scope)
delete scope;
global void finish(Database.BatchableContext BC)
I have few recommendation regarding your code:
- Make query selective.
[select id, contact__c, stagename from opportunity where contact__c != ''];is a bad query - Split large methods into few small methods. Method
executeis too large - Pass as
queryLocatornot justStringof query, but staticSOQLquery. It could prevent from having runtime exceptions to compile exceptions, that are more easy to fix. instead ofDatabase.getQueryLocator('select id from Account');useDatabase.getQueryLocator([select id from Account]); - Catch exceptions only if you know what to do with it, otherwise you will not receive any errors if those occur
try
delete contactsToDelete;
catch(Exception e) // is not a best practice
your code could be re-write to query Contacts, that are not in Contact__c on Opportunities
global class DeleteContact implements Database.Batchable<sObject>
private Date dateToDeleteTo;
global DeleteContact()
dateToDeleteTo = Date.today().addYears(-1).addDays(-3);
global Database.QueryLocator start(Database.BatchableContext BC)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
return Database.getQueryLocator([
select Id
from Contact
where Id not in (
select Contact__c
from Opportunity
where Contact__c != null
)
and RecordTypeId = :b2cId
and Email like '%@icslearn.co.uk'
and CreatedDate <= :dateToDeleteTo
]);
global void execute(Database.BatchableContext BC, List<Contact> scope)
delete scope;
global void finish(Database.BatchableContext BC)
answered 37 mins ago
Oleksandr Berehovskiy
6,95011633
6,95011633
add a comment |Â
add a comment |Â
up vote
3
down vote
You can easily optimize this code. First query Opportunity as child records instead of querying all opportunity in system. Which will also reduce your line of code.
global class DeleteContact implements Database.Batchable<sObject>
global date d = system.today().addYears(-1).addDays(-3);
//check and verify relationship name
public String query = 'select id, opportunity__c, RecordTypeId, email, customer_Number__c, (SELECT ID FROM Opportunity__r LIMIT 1) from contact where createddate <= :d';
global Database.QueryLocator start(Database.BatchableContext BC)
return Database.getQueryLocator(query);
global void execute(Database.BatchableContext BC, List<Contact> scope)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
List<Contact> contactsToDelete = new List<Contact>();
// just check the child list size . if its 0 then it don't have record and you can proceed to delete
for(Contact co : contactsInScope)
if(co.Opportunity__r.size() == 0 && co.RecordTypeId == b2cId && co.Customer_Number__c == '' && !co.email.contains('@icslearn.co.uk'))
contactsToDelete.add(co);
//As this is Asyn so try catch won't make a difference here and you can remove them
delete contactsToDelete;
global void finish(Database.BatchableContext BC)
add a comment |Â
up vote
3
down vote
You can easily optimize this code. First query Opportunity as child records instead of querying all opportunity in system. Which will also reduce your line of code.
global class DeleteContact implements Database.Batchable<sObject>
global date d = system.today().addYears(-1).addDays(-3);
//check and verify relationship name
public String query = 'select id, opportunity__c, RecordTypeId, email, customer_Number__c, (SELECT ID FROM Opportunity__r LIMIT 1) from contact where createddate <= :d';
global Database.QueryLocator start(Database.BatchableContext BC)
return Database.getQueryLocator(query);
global void execute(Database.BatchableContext BC, List<Contact> scope)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
List<Contact> contactsToDelete = new List<Contact>();
// just check the child list size . if its 0 then it don't have record and you can proceed to delete
for(Contact co : contactsInScope)
if(co.Opportunity__r.size() == 0 && co.RecordTypeId == b2cId && co.Customer_Number__c == '' && !co.email.contains('@icslearn.co.uk'))
contactsToDelete.add(co);
//As this is Asyn so try catch won't make a difference here and you can remove them
delete contactsToDelete;
global void finish(Database.BatchableContext BC)
add a comment |Â
up vote
3
down vote
up vote
3
down vote
You can easily optimize this code. First query Opportunity as child records instead of querying all opportunity in system. Which will also reduce your line of code.
global class DeleteContact implements Database.Batchable<sObject>
global date d = system.today().addYears(-1).addDays(-3);
//check and verify relationship name
public String query = 'select id, opportunity__c, RecordTypeId, email, customer_Number__c, (SELECT ID FROM Opportunity__r LIMIT 1) from contact where createddate <= :d';
global Database.QueryLocator start(Database.BatchableContext BC)
return Database.getQueryLocator(query);
global void execute(Database.BatchableContext BC, List<Contact> scope)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
List<Contact> contactsToDelete = new List<Contact>();
// just check the child list size . if its 0 then it don't have record and you can proceed to delete
for(Contact co : contactsInScope)
if(co.Opportunity__r.size() == 0 && co.RecordTypeId == b2cId && co.Customer_Number__c == '' && !co.email.contains('@icslearn.co.uk'))
contactsToDelete.add(co);
//As this is Asyn so try catch won't make a difference here and you can remove them
delete contactsToDelete;
global void finish(Database.BatchableContext BC)
You can easily optimize this code. First query Opportunity as child records instead of querying all opportunity in system. Which will also reduce your line of code.
global class DeleteContact implements Database.Batchable<sObject>
global date d = system.today().addYears(-1).addDays(-3);
//check and verify relationship name
public String query = 'select id, opportunity__c, RecordTypeId, email, customer_Number__c, (SELECT ID FROM Opportunity__r LIMIT 1) from contact where createddate <= :d';
global Database.QueryLocator start(Database.BatchableContext BC)
return Database.getQueryLocator(query);
global void execute(Database.BatchableContext BC, List<Contact> scope)
Id b2cId = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('B2C Contact').getRecordTypeId();
List<Contact> contactsToDelete = new List<Contact>();
// just check the child list size . if its 0 then it don't have record and you can proceed to delete
for(Contact co : contactsInScope)
if(co.Opportunity__r.size() == 0 && co.RecordTypeId == b2cId && co.Customer_Number__c == '' && !co.email.contains('@icslearn.co.uk'))
contactsToDelete.add(co);
//As this is Asyn so try catch won't make a difference here and you can remove them
delete contactsToDelete;
global void finish(Database.BatchableContext BC)
answered 35 mins ago
Tushar Sharma
23.9k52044
23.9k52044
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f235471%2fbatch-apex-requiring-two-queries-and-hitting-limits%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
