0

Getting Duplicate Id in list Error when I uploaded 300 plus task for this trigger.

public class contactActivityHandler {

public static void updateContact(List<Task> tks){ // Trigger.New comes as List here
    Set <Id> ContactIds = new Set<Id>();
    List <Contact> ContactList = new List<Contact>();

    for(Task t :tks) 
    {
        if(t.whoId!=null)
        {
            Schema.SObjectType tType= t.whoId.getSObjectType();
            if(tType == Contact.Schema.SObjectType)
            {
                ContactIds.add(t.WhoId);
            }
        }
    }
    //Querying the related Contacts based on whoId on Task
    Map<Id,Contact> ContactMap =  new Map<Id,Contact>([select id, Last_Contact_Date__c,Name, Last_Activity_TypeOfInteraction__c, LastActivityDate, Last_Activity_Subject__c,Last_Activity_Date__c, Last_Activity_Name__c from Contact where id in:ContactIds]);
    for(Task t :tks)
    {
        If((!t.Subject.contains('DFP sent')))
        {   
            for(Contact l : ContactMap.Values())
            {  
              If(t.ActivityDate >=l.Last_Contact_Date__c)
                {
                l.Last_Activity_Subject__c = t.subject;
                l.Last_Activity_Date__c = t.ActivityDate;
                l.Last_Activity_Name__c = l.Name;
                l.Last_Activity_TypeOfInteraction__c = t.Type_of_Interaction__c;
                ContactList.add(l);
                }
             } 
        }
    }  
    // updating the Lead
    if(ContactList.size()>0)
    {

        update ContactList;
    }
}//End of Update Contact

public static void updateOldContact(List<Task> tks, List<Task>tksOld){ // Trigger.New comes as List here

    Set<Id> ContactIds = new Set<Id>();
    Set<Id> OldContactIds = new Set<Id>(); //to get old contact ids
    List<Contact> ContactList = new List<Contact>();
    List<Contact> OldContactList = new List<Contact>();
    List<Contact> AllUpdateContactList = new List<Contact>();

    for(Task t :tks) // looping through Ids and saves as Contacts Ids?
    {
        if(t.whoId!=null)
        {
            Schema.SObjectType tType= t.whoId.getSObjectType();
            if(tType == Contact.Schema.SObjectType)
            {

                ContactIds.add(t.WhoId);
            }
        }
    }//End of First loop

    for(Task ot :tksOld) // looping through Ids and saves as Contacts Ids?
    {
        if(ot.whoId!=null)
        {
            Schema.SObjectType otType= ot.whoId.getSObjectType();
            if(otType == Contact.Schema.SObjectType)
            {

                OldContactIds.add(ot.WhoId); //Get old contact Id
            }
        }
    }//End of Second loop         


    //Querying the related Contacts based on whoId on Task
    for(Id conold : OldContactIds){
        if(ContactIds.contains(conold)==false){ //Check old id with new id
            Map<Id,Contact> OldContactMap =  new Map<Id,Contact>([select id, Last_Contact_Date__c,Name, Last_Activity_TypeOfInteraction__c, LastActivityDate, Last_Activity_Subject__c,Last_Activity_Date__c, Last_Activity_Name__c from Contact where id in:OldContactIds]);
            Map<Id,Contact> NewContactMap =  new Map<Id,Contact>([select id,Last_Contact_Date__c,Name, Last_Activity_TypeOfInteraction__c, LastActivityDate, Last_Activity_Subject__c,Last_Activity_Date__c, Last_Activity_Name__c from Contact where id in:ContactIds]);
            List<Task>  tskrecs = [select id,Subject,ActivityDate,Type_of_Interaction__c  from task where WhoId =: ContactIds Order By lastmodifieddate DESC LIMIT 1];
            List<Task>  Oldtskrecs = [select id,Subject,ActivityDate,Type_of_Interaction__c  from task where WhoId =: OldContactIds Order By lastmodifieddate DESC LIMIT 1];
            for(Task t :tskrecs)
            {
                If((!t.Subject.contains('DFP sent')))
                {   
                    for(Contact l : OldContactMap.Values())
                    {  
                        If(t.ActivityDate != null)
                        {
                            for(Contact nl : NewContactMap.values()){

                                nl.Last_Activity_Subject__c= t.subject;
                                nl.Last_Activity_Date__c = t.ActivityDate;
                                nl.Last_Activity_Name__c = l.Name;
                                nl.Last_Activity_TypeOfInteraction__c = t.Type_of_Interaction__c;
                                AllUpdateContactList.add(nl);
                             }
                        }
                    } 
                }
            }  
            for(Task t :Oldtskrecs){
                If((!t.Subject.contains('DFP sent')))
                {   
                    for(Contact l : OldContactMap.Values())
                    {  
                        If(t.ActivityDate != null)
                        {
                            l.Last_Activity_Subject__c = t.subject;
                            l.Last_Activity_Date__c = t.ActivityDate;
                            l.Last_Activity_Name__c = l.Name;
                            l.Last_Activity_TypeOfInteraction__c = t.Type_of_Interaction__c;
                            AllUpdateContactList.add(l);
                        }

                    }
                }

            }
            update AllUpdateContactList;
        }else if(ContactIds.contains(conold)== true ){
            updateContact(tks);
        }
    }    
}//End of Update Old Contact

}//End of Class

Error Message:

enter image description here

2

You're iterating over all Contacts inside our outer for loop for all Tasks. You should be affecting only the related Contact for this Task, which is found via contactMap.get(t.WhoId). (Assuming that the WhoId is a Contact).

for(Task t :tks)
{
    If((!t.Subject.contains('DFP sent')))
    {   
        for(Contact l : ContactMap.Values())
        {  
          If(t.ActivityDate >=l.Last_Contact_Date__c)
            {
            l.Last_Activity_Subject__c = t.subject;
            l.Last_Activity_Date__c = t.ActivityDate;
            l.Last_Activity_Name__c = l.Name;
            l.Last_Activity_TypeOfInteraction__c = t.Type_of_Interaction__c;
            ContactList.add(l);
            }
         } 
    }
}  

Even when you make that change, you are still vulnerable to this error if you have multiple Tasks related to the same Contact, because you'd add the Contact to ContactList once per related Task. Instead, accumulate a new Map<Id, Contact> with your Contacts-to-update, and check there for a Contact updated by previous Tasks. It'd look something like this (you may have to adjust for your real code):

    if (!t.Subject.contains('DFP sent') && t.WhoId.getSObjectType() == Contact.SObjectType) {
        Contact l = (contactsToUpdateMap.containsKey(t.WhoId) ? contactsToUpdateMap.get(t.WhoId) : contactMap.get(t.WhoId);

        l.Last_Activity_Subject__c = t.subject;
        l.Last_Activity_Date__c = t.ActivityDate;
        l.Last_Activity_Name__c = l.Name;
        l.Last_Activity_TypeOfInteraction__c = t.Type_of_Interaction__c;

        contactsToUpdateMap.put(t.WhoId, l);
    }

Later:

update contactsToUpdateMap.values();
1
  • Thank you, David. I will a try. Let you know.
    – calo
    Jul 19 '19 at 15:41
0

You are adding the same contact into the update list multiple times, you need to remove the duplicates from the list before updating them.

for every task, you are iterating all the contacts and changes the same contact values and adding it to the ContactList again and again(not a best practice).

For your case, you need to remove the duplicates from the list before doing a DML operation.

Instead of the list take a map like this:

//Take a map to update
Map<Id,Contact> updateContactsMap = new Map<Id,Contact>();
//Querying the related Contacts based on whoId on Task
Map<Id,Contact> ContactMap =  new Map<Id,Contact>([select id, Last_Contact_Date__c,Name, Last_Activity_TypeOfInteraction__c, LastActivityDate, Last_Activity_Subject__c,Last_Activity_Date__c, Last_Activity_Name__c from Contact where id in:ContactIds]);
for(Task t :tks) {
    If((!t.Subject.contains('DFP sent'))) {   
        for(Contact l : ContactMap.Values()) {  
            If(t.ActivityDate >=l.Last_Contact_Date__c) {
               //your logic here
               //add it to map, map won't allow duplicates
               updateContactsMap.put(l.Id, l);
            }
        } 
    }
}
//do the DML on map values
if(updateContactsMap.size()>0) {
    UPDATE updateContactsMap.values();
}

If you explain more about the use case, then it will be more helpful to give the a best solution.

3
  • Thanks, Lokesh. I will give it a try as well.
    – calo
    Jul 19 '19 at 15:43
  • The principle is good, but this code is still incorrect because it inspects all Contacts for every Task.
    – David Reed
    Jul 19 '19 at 15:47
  • Accepted @DavidReed, If the requirement is clear then we can give the best possible solution. Your answer is right, but I've seen it after I made this post
    – Lokesh
    Jul 19 '19 at 15:52
0

This is occurring because for every task "t" , you are looping around the queried contactMap values again and again and adding the qualified contacts in the contactList which can contain duplicate contact records. You can try out the below code:

public static void updateContact(List<Task> tks){ // Trigger.New comes as List here
    Set <Id> ContactIds = new Set<Id>();
    List <Contact> ContactList = new List<Contact>();

    for(Task t :tks) 
    {
        if(t.whoId!=null)
        {
            Schema.SObjectType tType= t.whoId.getSObjectType();
            if(tType == Contact.Schema.SObjectType)
            {
                ContactIds.add(t.WhoId);
            }
        }
    }
    //Querying the related Contacts based on whoId on Task
    Map<Id,Contact> ContactMap =  new Map<Id,Contact>([select id, Last_Contact_Date__c,Name, Last_Activity_TypeOfInteraction__c, LastActivityDate, Last_Activity_Subject__c,Last_Activity_Date__c, Last_Activity_Name__c from Contact where id in:ContactIds]);
// Updated Code- start
    for(Task t :tks){
        If((!t.Subject.contains('DFP sent'))){
            Contact l = ContactMap != null && ContactMap.containsKey(t.WhoId) ? ContactMap.get(t.WhoId) : null;
            If(l != null && t.ActivityDate >= l.Last_Contact_Date__c){
                l.Last_Activity_Subject__c = t.subject;
                l.Last_Activity_Date__c = t.ActivityDate;
                l.Last_Activity_Name__c = l.Name;
                l.Last_Activity_TypeOfInteraction__c = t.Type_of_Interaction__c;
                ContactList.add(l);
            }
        }
    }
// Updated Code- end
    // updating the Lead
    if(ContactList.size()>0)
    {

        update ContactList;
    }
}//End of Update Contact

The same change you need to do in the "updateOldContact" method as well

0

I was able to fix it with below code. It worked when I inserted 300+ task in there with No Errors.

 public class contactActivityHandler {

    public static void updateContact(List<Task> tks){ // Trigger.New comes as List here
        Set <Id> ContactIds = new Set<Id>();
        List <Contact> ContactList = new List<Contact>();

        for(Task t :tks) 
        {
            if(t.whoId!=null)
            {
                Schema.SObjectType tType= t.whoId.getSObjectType();
                if(tType == Contact.Schema.SObjectType)
                {
                    ContactIds.add(t.WhoId);
                }
            }
        }
        //Querying the related Contacts based on whoId on Task
        Map<Id,Contact> ContactMap =  new Map<Id,Contact>([select id, Last_Contact_Date__c,Name, Last_Activity_TypeOfInteraction__c, LastActivityDate, Last_Activity_Subject__c,Last_Activity_Date__c, Last_Activity_Name__c from Contact where id in:ContactIds]);
        for(Task t :tks)
        {
            If((!t.Subject.contains('DFP sent')))
            {   
                for(Contact l : ContactMap.Values())
                {  
                  If(t.ActivityDate >=l.Last_Contact_Date__c)
                    {
                    l.Last_Activity_Subject__c = t.subject;
                    l.Last_Activity_Date__c = t.ActivityDate;
                    l.Last_Activity_Name__c = l.Name;
                    l.Last_Activity_TypeOfInteraction__c = t.Type_of_Interaction__c;
                    ContactList.add(l);
                    }
                 } 
            }
        }  
        // updated code.
        map<id,Contact> conMap = new map<id,Contact>();
        conMap.putAll(ContactList);

        // updating the Lead

        if(conMap.size()>0)
        {


            update conMap.Values();
        }
    }//End of Update Contact

    public static void updateOldContact(List<Task> tks, List<Task>tksOld){ // Trigger.New comes as List here

        Set<Id> ContactIds = new Set<Id>();
        Set<Id> OldContactIds = new Set<Id>(); //to get old contact ids
        List<Contact> ContactList = new List<Contact>();
        List<Contact> OldContactList = new List<Contact>();
        List<Contact> AllUpdateContactList = new List<Contact>();

        for(Task t :tks) // looping through Ids and saves as Contacts Ids?
        {
            if(t.whoId!=null)
            {
                Schema.SObjectType tType= t.whoId.getSObjectType();
                if(tType == Contact.Schema.SObjectType)
                {

                    ContactIds.add(t.WhoId);
                }
            }
        }//End of First loop

        for(Task ot :tksOld) // looping through Ids and saves as Contacts Ids?
        {
            if(ot.whoId!=null)
            {
                Schema.SObjectType otType= ot.whoId.getSObjectType();
                if(otType == Contact.Schema.SObjectType)
                {

                    OldContactIds.add(ot.WhoId); //Get old contact Id
                }
            }
        }//End of Second loop         


        //Querying the related Contacts based on whoId on Task
        for(Id conold : OldContactIds){
            if(ContactIds.contains(conold)==false){ //Check old id with new id
                Map<Id,Contact> OldContactMap =  new Map<Id,Contact>([select id, Last_Contact_Date__c,Name, Last_Activity_TypeOfInteraction__c, LastActivityDate, Last_Activity_Subject__c,Last_Activity_Date__c, Last_Activity_Name__c from Contact where id in:OldContactIds]);
                Map<Id,Contact> NewContactMap =  new Map<Id,Contact>([select id,Last_Contact_Date__c,Name, Last_Activity_TypeOfInteraction__c, LastActivityDate, Last_Activity_Subject__c,Last_Activity_Date__c, Last_Activity_Name__c from Contact where id in:ContactIds]);
                List<Task>  tskrecs = [select id,Subject,ActivityDate,Type_of_Interaction__c  from task where WhoId =: ContactIds Order By lastmodifieddate DESC LIMIT 1];
                List<Task>  Oldtskrecs = [select id,Subject,ActivityDate,Type_of_Interaction__c  from task where WhoId =: OldContactIds Order By lastmodifieddate DESC LIMIT 1];
                for(Task t :tskrecs)
                {
                    If((!t.Subject.contains('DFP sent')))
                    {   
                        for(Contact l : OldContactMap.Values())
                        {  
                            If(t.ActivityDate != null)
                            {
                                for(Contact nl : NewContactMap.values()){

                                    nl.Last_Activity_Subject__c= t.subject;
                                    nl.Last_Activity_Date__c = t.ActivityDate;
                                    nl.Last_Activity_Name__c = l.Name;
                                    nl.Last_Activity_TypeOfInteraction__c = t.Type_of_Interaction__c;
                                    AllUpdateContactList.add(nl);
                                 }
                            }
                        } 
                    }
                }  
                for(Task t :Oldtskrecs){
                    If((!t.Subject.contains('DFP sent')))
                    {   
                        for(Contact l : OldContactMap.Values())
                        {  
                            If(t.ActivityDate != null)
                            {
                                l.Last_Activity_Subject__c = t.subject;
                                l.Last_Activity_Date__c = t.ActivityDate;
                                l.Last_Activity_Name__c = l.Name;
                                l.Last_Activity_TypeOfInteraction__c = t.Type_of_Interaction__c;
                                AllUpdateContactList.add(l);
                            }

                        }
                    }

                }
                update AllUpdateContactList;
            }else if(ContactIds.contains(conold)== true ){
                updateContact(tks);
            }
        }    
    }//End of Update Old Contact

}//End of Class

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.