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
Karthikeyan ChandranKarthikeyan Chandran 

Batch Class help needed for Contacts not related to Case

Hi Team,

Can anyone help me to fix this issue to Batch Class for Contacts not related to Case ASAP?

Thanks & Regards,
Karthikeyan Chandran
Best Answer chosen by Karthikeyan Chandran
Agustina GarciaAgustina Garcia
Hi,

As Amit says, if you post your code, it can help us to identify where is your error.

Regarding Charisse code, is doing the process in the other way around. It is removing cases that are not related with a contact. In addition, Batch process must override 3 methods, start, execute and finish and above code doesn't include finish one. For more information take a look here (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_batch_interface.htm).

In any case, this is an example of what I would do.
 
public class BatchDeleteContactWithNoCases implements Database.Batchable<sObject>
{
	public static Set<Id> contactId = new Set<Id>();
    
    public BatchDeleteContactWithNoCases()
    {
		for(Case theCase : [SELECT Id, ContactId FROM Case])
        {
            contactId.add(theCase.ContactId);
        }
    }
    public Database.QueryLocator start(Database.BatchableContext bc)
    {
        String qry = 'SELECT Id FROM Contact Where Id IN : contactId';
        
        return Database.getQueryLocator(qry);
    }
    
    public void execute(Database.BatchableContext bc, List<SObject> records)
    {
        delete records;
    }
    
    public void finish(Database.BatchableContext bc)
    {
        //You can use this method to send an email once the async process ends
    }
}
Hope this helps.

Agustina
 

All Answers

Agustina GarciaAgustina Garcia
What do you exactly need?
Karthikeyan ChandranKarthikeyan Chandran
I want to delete the Contacts that are not related to Case.
Karthikeyan ChandranKarthikeyan Chandran
Hi Agustina Garcia,

Any idea about this?
Charisse de BelenCharisse de Belen
Karthikeyan,

Have you tried something like this?
public class BatchDeleteCasesWithNoContacts implements Database.Batchable<sObject> {
	
    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(
			[SELECT Id FROM Case WHERE Contact.Id = null]        
        );
    }
    
    public void execute(Database.BatchableContext bc, List<Case> records) {
        delete records;
    }
    
    public void finish(Database.BatchableContext bc) {
        // Perform any final logic here 
    }
    
}

 
Amit Chaudhary 8Amit Chaudhary 8
Hi Karthikeyan,

Please post your code so that we can help you
Agustina GarciaAgustina Garcia
Hi,

As Amit says, if you post your code, it can help us to identify where is your error.

Regarding Charisse code, is doing the process in the other way around. It is removing cases that are not related with a contact. In addition, Batch process must override 3 methods, start, execute and finish and above code doesn't include finish one. For more information take a look here (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_batch_interface.htm).

In any case, this is an example of what I would do.
 
public class BatchDeleteContactWithNoCases implements Database.Batchable<sObject>
{
	public static Set<Id> contactId = new Set<Id>();
    
    public BatchDeleteContactWithNoCases()
    {
		for(Case theCase : [SELECT Id, ContactId FROM Case])
        {
            contactId.add(theCase.ContactId);
        }
    }
    public Database.QueryLocator start(Database.BatchableContext bc)
    {
        String qry = 'SELECT Id FROM Contact Where Id IN : contactId';
        
        return Database.getQueryLocator(qry);
    }
    
    public void execute(Database.BatchableContext bc, List<SObject> records)
    {
        delete records;
    }
    
    public void finish(Database.BatchableContext bc)
    {
        //You can use this method to send an email once the async process ends
    }
}
Hope this helps.

Agustina
 
This was selected as the best answer
Karthikeyan ChandranKarthikeyan Chandran
@All,

Here my code,
 
global class BatchDeleteContacts implements Database.Batchable<sObject> {

   Map<String, List<Contact>> contMap = new Map<String, List<Contact>>();

   global Database.QueryLocator start(Database.BatchableContext BC)
{
//I want to query the contact records that are not related to case records.
   String query = 'Select Id from Contact Limit 5';
      return Database.getQueryLocator(query);
   }

   global void execute(Database.BatchableContext BC, List<sObject> scope){
      delete scope;
      DataBase.emptyRecycleBin(scope);
   }

   global void finish(Database.BatchableContext BC){
   }
}

 
Charisse de BelenCharisse de Belen
Ah yes, I had renamed my class from BatchDeleteCaselessContacts to BatchDeleteCasesWithNoContacts and forgot to double check that my logic still matched your problem. Sorry about that!

In that case, Agustina's code looks correct. The only issue is that in the start method, the query needs to use the "NOT" statement like this:
String qry = 'SELECT Id FROM Contact Where Id NOT IN : contactId';
This is because contactId is a set of all the Contacts that do have Cases. So you want to select all the Contacts that are not in that set.
 
Amit Chaudhary 8Amit Chaudhary 8
Please check below post to learn about Batch job
1) http://amitsalesforce.blogspot.com/2016/02/batch-apex-in-salesforce-test-class-for.html

Batch Apex
A Batch class allows you to define a single job that can be broken up into manageable chunks that will be processed separately.


When to use Batch Apex
One example is if you need to make a field update to every Account in your organization. If you have 10,001 Account records in your org, this is impossible without some way of breaking it up. So in the start() method, you define the query you're going to use in this batch context: 'select Id from Account'. Then the execute() method runs, but only receives a relatively short list of records (default 200). Within the execute(), everything runs in its own transactional context, which means almost all of the governor limits only apply to that block. Thus each time execute() is run, you are allowed 150 queries and 50,000 DML rows and so on. When that execute() is complete, a new one is instantiated with the next group of 200 Accounts, with a brand new set of governor limits. Finally the finish() method wraps up any loose ends as necessary, like sending a status email.


Sample Batch Apex
1) Start method is automatically called at the beginning of the apex job. This method will collect record or objects on which the operation should be performed. These record are divided into subtasks & passes those to execute method.

2) Execute Method performs operation which we want to perform on the records fetched from start method.

3) Finish method executes after all batches are processed. Use this method to send confirmation email notifications.

Agustina's code looks perfect as per your requirement . Just change the code like below
public class BatchDeleteContactWithNoCases implements Database.Batchable<sObject>
{
	public static Set<Id> contactId = new Set<Id>();
    
    public BatchDeleteContactWithNoCases()
    {
		for(Case theCase : [SELECT Id, ContactId FROM Case])
        {
            contactId.add(theCase.ContactId);
        }
    }
    public Database.QueryLocator start(Database.BatchableContext bc)
    {
        String qry = 'SELECT Id FROM Contact Where Id Not IN : contactId';
        
        return Database.getQueryLocator(qry);
    }
    
    public void execute(Database.BatchableContext bc, List<SObject> records)
    {
        delete records;
    }
    
    public void finish(Database.BatchableContext bc)
    {
        //You can use this method to send an email once the async process ends
    }
}



Let us know if this will help you
 
Karthikeyan ChandranKarthikeyan Chandran
Yes,

It's working now.

Thanks @All for the help!!!