控制器执行限制确保在Force.com多租户平台上有效地使用资源。 它是由Salesforce.com指定的对代码执行有效处理的限制。
什么是调节器限制?
我们知道,Apex在多租户环境中运行; 即单个资源由所有客户和组织共享。 因此,有必要确保没有人垄断资源,因此Salesforce.com已经创建了一组管理和限制代码执行的限制。 每当任何一个调节器限制被越过,它将抛出错误,并将停止程序的执行。
从开发人员的角度来看,确保我们的代码是可扩展的并且不应该达到极限是至关重要的。所有这些限制都适用于每个交易。 单个触发器执行一个事务。
正如我们所看到的,触发器设计模式是一种避免极限误差的方法。 让我们看看一些重要的限制。
避免SOQL查询限制
每个事务只能发出100个查询,也就是说,当代码发出超过100个SOQL查询时,它会抛出错误。
例如:
以下是显示如何达到SOQL查询限制的示例:
以下触发器遍历客户列表,并使用字符串“Ok to Pay”更新子记录(发票)描述。
//Heper class:Below code needs o be checked. public class CustomerTriggerHelper { public static void isAfterUpdateCall(Trigger.new) { createInvoiceRecords(trigger.new);//Method call updateCustomerDescription(trigger.new); } //Method To Create Invoice Records public static void createInvoiceRecords (List<apex_customer__c> customerList) { for (APEX_Customer__c objCustomer: customerList) { if (objCustomer.APEX_Customer_Status__c == 'Active' && trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {//condition to check the old value and new value APEX_Invoice__c objInvoice = new APEX_Invoice__c(); objInvoice.APEX_Status__c = 'Pending'; InvoiceList.add(objInvoice); } } insert InvoiceList;//DML to insert the Invoice List in SFDC } //Method to update the invoice records public static updateCustomerDescription (List<apex_customer__c> customerList) { for (APEX_Customer__c objCust: customerList) { List<apex_invoice__c> invList = [SELECT Id, Name, APEX_Description__c FROM APEX_Invoice__c WHERE APEX_Customer__c = :objCust.id];//This query will fire for the number of records customer list has and will hit the governor limit when records are more than 100 for (APEX_Invoice__c objInv: invList) { objInv.APEX_Description__c = 'OK To Pay'; update objInv;//Update invoice, this will also hit the governor limit for DML if large number(150) of records are there } } } }
当方法'updateCustomerDescription'被调用,并且客户记录的数量大于100时,它将达到SOQL限制。
为了避免这种情况,不要在For循环中写入SOQL查询。 在这种情况下,SOQL查询已经写入for循环。
下面是我们可以避免DML以及SOQL限制的示例。 我们使用嵌套关系查询来获取发票记录,并使用上下文变量trigger.newMap来获取id和Customer记录的映射。
//SOQL-Good Way to Write Query and avoid limit exception //Helper Class public class CustomerTriggerHelper { public static void isAfterUpdateCall(Trigger.new) { createInvoiceRecords(trigger.new);//Method call updateCustomerDescription(trigger.new, trigger.newMap); } //Method To Create Invoice Records public static void createInvoiceRecords (List<apex_customer__c> customerList) { for (APEX_Customer__c objCustomer: customerList) { if (objCustomer.APEX_Customer_Status__c == 'Active' && trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {//condition to check the old value and new value APEX_Invoice__c objInvoice = new APEX_Invoice__c(); objInvoice.APEX_Status__c = 'Pending'; InvoiceList.add(objInvoice); } } insert InvoiceList;//DML to insert the Invoice List in SFDC } //Method to update the invoice records public static updateCustomerDescription (List<apex_customer__c> customerList, Map<id, apex_customer__c> newMapVariable) { List<apex_customer__c> customerListWithInvoice = [SELECT id, Name,(SELECT Id, Name, APEX_Description__c FROM APEX_Invoice__r) FROM APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];//Query will be for only one time and fetches all the records List<apex_invoice__c> invoiceToUpdate = new List<apex_invoice__c>(); for (APEX_Customer__c objCust: customerList) { for (APEX_Invoice__c objInv: invList) { objInv.APEX_Description__c = 'OK To Pay'; invoiceToUpdate.add(objInv);//Add the modified records to List } } update invoiceToUpdate; } }
DML批量调用
正如我们在许多示例中看到的,我们一直在列表中添加修改的记录,然后对该列表执行DML操作,而不是对单个记录执行DML。 下面是同样的例子。 这是批量触发器以及触发器帮助器类模式的示例。 您必须先保存帮助程序类,然后保存触发器。
注意:将以下代码粘贴到我们之前创建的“CustomerTriggerHelper”类中。
//Helper Class public class CustomerTriggerHelper { public static void isAfterUpdateCall(List<apex_customer__c> customerList, Map<id, apex_customer__c> mapIdToCustomers, Map<id, apex_customer__c> mapOldItToCustomers) { createInvoiceRecords(customerList, mapOldItToCustomers);//Method call updateCustomerDescription(customerList,mapIdToCustomers, mapOldItToCustomers); } //Method To Create Invoice Records public static void createInvoiceRecords (List<apex_customer__c> customerList, Map<id, apex_customer__c> mapOldItToCustomers) { List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>(); List<apex_customer__c> customerToInvoice = [SELECT id, Name FROM APEX_Customer__c LIMIT 1]; for (APEX_Customer__c objCustomer: customerList) { if (objCustomer.APEX_Customer_Status__c == 'Active' && mapOldItToCustomers.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {//condition to check the old value and new value APEX_Invoice__c objInvoice = new APEX_Invoice__c(); objInvoice.APEX_Status__c = 'Pending'; objInvoice.APEX_Customer__c = objCustomer.id; InvoiceList.add(objInvoice); } } system.debug('InvoiceList&&&'+InvoiceList); insert InvoiceList;//DML to insert the Invoice List in SFDC. This also follows the Bulk pattern } //Method to update the invoice records public static void updateCustomerDescription (List<apex_customer__c> customerList, Map<id, apex_customer__c> newMapVariable, Map<id, apex_customer__c> oldCustomerMap) { List<apex_customer__c> customerListWithInvoice = [SELECT id, Name,(SELECT Id, Name, APEX_Description__c FROM Invoices__r) FROM APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];//Query will be for only one time and fetches all the records List<apex_invoice__c> invoiceToUpdate = new List<apex_invoice__c>(); List<apex_invoice__c> invoiceFetched = new List<apex_invoice__c>(); invoiceFetched = customerListWithInvoice[0].Invoices__r; system.debug('invoiceFetched'+invoiceFetched); system.debug('customerListWithInvoice****'+customerListWithInvoice); for (APEX_Customer__c objCust: customerList) { system.debug('objCust.Invoices__r'+objCust.Invoices__r); if (objCust.APEX_Active__c == true && oldCustomerMap.get(objCust.id).APEX_Active__c == false) { for (APEX_Invoice__c objInv: invoiceFetched) { system.debug('I am in For Loop'+objInv); objInv.APEX_Description__c = 'OK To Pay'; invoiceToUpdate.add(objInv);//Add the modified records to List } } } system.debug('Value of List ***'+invoiceToUpdate); update invoiceToUpdate;//This statement is Bulk DML which performs the DML on List and avoids the DML Governor limit } } //Trigger Code for this class: Paste this code in 'Customer_After_Insert' trigger on Customer Object trigger Customer_After_Insert on APEX_Customer__c (after update) { CustomerTriggerHelper.isAfterUpdateCall(Trigger.new, trigger.newMap, trigger.oldMap);//Trigger calls the helper class and does not have any code in Trigger }
其他Salesforce Governor限制
以下是一些重要的Salesforce Governor限制,我们需要记住。 你可以检查其他Salesforce Governor限制以及使用Salesdorce.com Apex开发人员指南。
描述 | 限制 |
---|---|
Total heap size 总堆大小 |
6 MB / 12 MB |
Total number of DML statements issued 发出的DML语句的总数 |
150 |
Total number of records retrieved by a single SOSL query 单个SOSL查询检索的记录总数 |
2000 |
Total number of SOSL queries issued 发出的SOSL查询的总数 |
20 |
Total number of records retrieved by Database.getQueryLocator Database.getQueryLocator检索的记录总数 |
10000 |
Total number of records retrieved by SOQL queries 通过SOQL查询检索的记录总数 |
50000 |