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
Abhishek RayAbhishek Ray 

Deploying a trigger : System.Lim​itExceptio​n

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) {}

    }

  }

}

 

 
Starz26Starz26

get your soql outside of the for loop of for(cases c : cases)

kerwintangkerwintang

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!

Abhishek RayAbhishek Ray

Can you please explain me more. I don't have experience in Trigger.

kerwintangkerwintang

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.

Abhishek RayAbhishek Ray

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) {}

    }

  }

}

kerwintangkerwintang

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.