+ Start a Discussion
viadeoviadeo 

Duplicate id in list

Hi all

 

i have a this error when i run my test 

CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, workflow2: execution of AfterUpdate caused by: System.ListException: Duplicate id in list: 

 

this my trigger  :


trigger workflow2 on Contract (after update) {
List<Account>accList=new List <Account>();
set<id>accIds = new Set<id>();
for(contract c:trigger.new)
{
accIds.add(c.AccountId);
}
Map<id,Account>accMap=new Map<id,Account>([Select(select status from contrats__r)from account Where id in :accIds]);
List<contract> myContracts =[select AccountId from contract where AccountId in :accIds and status='activé'] ;


Set<ID> myAccountsIDs = new Set<ID>(); // here we will have only the ID's of those accounts that have a contract in status 'activé'
for (contract c : myContracts)
{
myAccountsIDs.add(c.AccountId);
}
for(contract c :trigger.new)
{
account ac=accMap.get(c.AccountId);
if(c.status=='activé')
{

ac.A_I__c='active';

}


if(c.status=='expiré'&& myAccountsIDs.contains(c.AccountId) == false)
{

ac.A_I__c='inactive';

}
accList.add(ac);
}
update accList;
}

 

thanks for your help

Best Answer chosen by Admin (Salesforce Developers) 
viadeoviadeo

Hi,

 

Thanks all for your answers .

I finally found a solution ,use Map because with it duplicate isn't allowed .

my trigger  :

 

 

trigger workflow2 on Contract (after update) {
Map<id,Account>accList=New Map<id,Account>();
List<Contract>conlist;
if(trigger.IsUpdate)
{
conlist=trigger.new;
}

set<id>accIds = new Set<id>();
for(Contract c:conlist){
accIds.add(c.accountId);
}
List<account>acclist2=new List<account>([Select id from account Where id in :accIds]);
Map<id,Account>CMap=new Map<id,Account>();

for(Account a :acclist2)
{
CMap.put(a.id,a);
}
List<contract> myContracts=[select AccountId from contract where AccountId in :accIds and status='activé'];
Set<ID> myAccountsIDs = new Set<ID>();
for (contract c : myContracts)
{
myAccountsIDs.add(c.AccountId);
}
if(trigger.IsUpdate)
{
for(contract c :trigger.new)
{
account ac=CMap.get(c.AccountId);
if(c.status=='activé')
{

ac.A_I__c='active';
}
if(c.status=='expiré'&& myAccountsIDs.contains(c.accountId) == false)
{
ac.A_I__c='inactive';
}
accList.put(ac.id,ac);
}


}
update accList.values();
}

All Answers

dmchengdmcheng

You are getting the Duplicate id in list error because you have a Duplicate id in your list.

 

You should use system.debug() and study your debug logs to see where you are adding the same account row into the list again.

Aar3538Aar3538

Hello,

 

In your Contract trigger, you are using a map to retrieve and update Accounts from the Contracts.  As a result some of your Contracts are probably looking up to the same Account so the variable accList contains the same Account multiple times.  This is a problem because salesforce will throw an error when you attempt to update accList.

 

Rather then looping through the Trigger.new at the bottom, I think it would be best to change that Account map to a list and loop through the accounts instead.  You can create a ContractToAccount map so you can retrieve the Contracts and compare the active status of the Contracts that way.

 

Please note that this still is not a complete fix, because if you have multiple Contracts updating but all of them point to the same Account, it will be uncertain sure which Contract will update the Account last. 

 

Hope this helps.

 

 

 

 

viadeoviadeo

Hi,

 

Thanks all for your answers .

I finally found a solution ,use Map because with it duplicate isn't allowed .

my trigger  :

 

 

trigger workflow2 on Contract (after update) {
Map<id,Account>accList=New Map<id,Account>();
List<Contract>conlist;
if(trigger.IsUpdate)
{
conlist=trigger.new;
}

set<id>accIds = new Set<id>();
for(Contract c:conlist){
accIds.add(c.accountId);
}
List<account>acclist2=new List<account>([Select id from account Where id in :accIds]);
Map<id,Account>CMap=new Map<id,Account>();

for(Account a :acclist2)
{
CMap.put(a.id,a);
}
List<contract> myContracts=[select AccountId from contract where AccountId in :accIds and status='activé'];
Set<ID> myAccountsIDs = new Set<ID>();
for (contract c : myContracts)
{
myAccountsIDs.add(c.AccountId);
}
if(trigger.IsUpdate)
{
for(contract c :trigger.new)
{
account ac=CMap.get(c.AccountId);
if(c.status=='activé')
{

ac.A_I__c='active';
}
if(c.status=='expiré'&& myAccountsIDs.contains(c.accountId) == false)
{
ac.A_I__c='inactive';
}
accList.put(ac.id,ac);
}


}
update accList.values();
}

This was selected as the best answer
Amjad OmarAmjad Omar
This is very helpful.
Summary:

A) List won't give you a problem when you add a duplicate to the list; but it will give you a problem during run-time when it actually finds duplicates during an update to the list.
B) A Map won't allow for a duplicate to be entered to begin with.