You need to sign in to do that
Don't have an account?

Deploying a trigger : System.LimitException
Hello,
I try to deploy a trigger and its test class in production but I have this error :
Failure Message: "System.LimitException: Too many SOQL queries: 101", Failure Stack Trace: "Trigger.CaseTeamTrigger: line 14, column 1" ...
The code coverage of this trigger is 100%.
I think this is due to another test class for another trigger but the both (the 2 triggers and the 2 test classes) are on the same object (Case).
The other trigger is already deployed.
How can I solve this problem ?
Thank you.
Here is my code:
trigger CaseTeamTrigger on Case (after insert, after update) {
Map<Id, CaseTeamMember> membersToAdd = new Map<Id, CaseTeamMember>();
List<Case> cases = [Select Id,OwnerId,RecordTypeId,RecordType.Name
from Case where id IN :Trigger.newMap.keySet()];
for (Case c : cases)
{
if(c.RecordType.Name =='Legal' || c.RecordType.Name =='Security/Quality Request'){
membersToAdd.put(c.Id, new CaseTeamMember(ParentId = c.Id, MemberId = UserInfo.getUserId()));
}
if (!membersToAdd.isEmpty()) {
try {
CaseTeamRole caseTeamRole = [SELECT Id FROM CaseTeamRole WHERE Name = 'Creator' LIMIT 100];
for (CaseTeamMember ctm : membersToAdd.values()) {
ctm.TeamRoleId = caseTeamRole.Id;
}
for (CaseTeamMember ctm : [SELECT Id, MemberId, ParentId
FROM CaseTeamMember
WHERE ParentId IN :membersToAdd.keySet()
AND MemberId = :UserInfo.getUserId()
ORDER BY ParentId])
{
if (membersToAdd.containsKey(ctm.ParentId)) {
membersToAdd.remove(ctm.ParentId);
}
}
if (!membersToAdd.isEmpty()) {
insert membersToAdd.values();
}
} catch (System.QueryException qe) {}
}
}
}
get your soql outside of the for loop of for(cases c : cases)
My guess would be this line:
CaseTeamRole caseTeamRole = [SELECT Id FROM CaseTeamRole WHERE Name = 'Creator' LIMIT 100];
Since this line is inside the loop through all the retrieved Case Records, there is a possiblity of the LimitException if the number of retrieved Case Records is large.
If this is the problem then you can move the CaseTeamRole retrieval outside the loop. Hope this helps!
Can you please explain me more. I don't have experience in Trigger.
Basically in this line:
List<Case> cases = [Select Id,OwnerId,RecordTypeId,RecordType.Name
from Case where id IN :Trigger.newMap.keySet()];
If you retrieve 1000 Case records, then it will loop through those 1000 cases:
for (Case c : cases)
Inside the loop you have this:
CaseTeamRole caseTeamRole = [SELECT Id FROM CaseTeamRole WHERE Name = 'Creator' LIMIT 100];
Which means you will perform the query for each Case, which is 1000 records for this example. This will violate the System Limit of 100 queries in the transaction.
The solution would be to get this line:
CaseTeamRole caseTeamRole = [SELECT Id FROM CaseTeamRole WHERE Name = 'Creator' LIMIT 100];
And put it before this line:
List<Case> cases = [Select Id,OwnerId,RecordTypeId,RecordType.Name
from Case where id IN :Trigger.newMap.keySet()];
So you only perform the CaseTeamRole query once for the whole transaction, not once for each Case.
Hope this helps.
I followed your step but again the same error: Failure Message: "System.LimitException: Too many SOQL queries: 101", Failure Stack Trace: "Trigger.CaseTeamTrigger: line 20, column 1"
The the line 20 is the green one highlighted
trigger CaseTeamTrigger on Case (after insert, after update) {
Map<Id, CaseTeamMember> membersToAdd = new Map<Id, CaseTeamMember>();
CaseTeamRole caseTeamRole = [SELECT Id FROM CaseTeamRole WHERE Name = 'Creator' LIMIT 100];
List<Case> cases = [Select Id,OwnerId,RecordTypeId,RecordType.Name
from Case where id IN :Trigger.newMap.keySet()];
for (Case c : cases)
{
if(c.RecordTypeID =='012800000003fik' || c.RecordTypeID =='012800000003hnA'){
membersToAdd.put(c.Id, new CaseTeamMember(ParentId = c.Id, MemberId = UserInfo.getUserId()));
}
if (!membersToAdd.isEmpty()) {
try {
for (CaseTeamMember ctm : membersToAdd.values()) {
ctm.TeamRoleId = caseTeamRole.Id;
}
for (CaseTeamMember ctm : [SELECT Id, MemberId, ParentId
FROM CaseTeamMember
WHERE ParentId IN :membersToAdd.keySet()
AND MemberId = :UserInfo.getUserId()
ORDER BY ParentId])
{
if (membersToAdd.containsKey(ctm.ParentId)) {
membersToAdd.remove(ctm.ParentId);
}
}
if (!membersToAdd.isEmpty()) {
insert membersToAdd.values();
}
} catch (System.QueryException qe) {}
}
}
}
Same issue -- the highlighted line performs a query inside the loop.
My suggestion is to take out this highlighted query and put it before the loop of Case records. Put the resultset in a Map and that's what you use inside the loop.
e.g. before the loop:
List<CaseTeamMember> ctms = [select Id, MemberId, ParentId from CaseTeamMember where MemberId = :UserInfo.getUserId()];
then inside the loop:
for(CaseTeamMember ctm:ctms){
if (membersToAdd.containsKey(ctm.ParentId)) {
membersToAdd.remove(ctm.ParentId);
}
}
Try it out and hope this helps you.