控制器執(zhí)行限制確保在Force.com多租戶平臺(tái)上有效地使用資源。 它是由Salesforce.com指定的對(duì)代碼執(zhí)行有效處理的限制。
我們知道,Apex在多租戶環(huán)境中運(yùn)行; 即單個(gè)資源由所有客戶和組織共享。 因此,有必要確保沒(méi)有人壟斷資源,因此Salesforce.com已經(jīng)創(chuàng)建了一組管理和限制代碼執(zhí)行的限制。 每當(dāng)任何一個(gè)調(diào)節(jié)器限制被越過(guò),它將拋出錯(cuò)誤,并將停止程序的執(zhí)行。
從開(kāi)發(fā)人員的角度來(lái)看,確保我們的代碼是可擴(kuò)展的并且不應(yīng)該達(dá)到極限是至關(guān)重要的。所有這些限制都適用于每個(gè)交易。 單個(gè)觸發(fā)器執(zhí)行一個(gè)事務(wù)。
正如我們所看到的,觸發(fā)器設(shè)計(jì)模式是一種避免極限誤差的方法。 讓我們看看一些重要的限制。
每個(gè)事務(wù)只能發(fā)出100個(gè)查詢,也就是說(shuō),當(dāng)代碼發(fā)出超過(guò)100個(gè)SOQL查詢時(shí),它會(huì)拋出錯(cuò)誤。
例如:
以下是顯示如何達(dá)到SOQL查詢限制的示例:
以下觸發(fā)器遍歷客戶列表,并使用字符串“Ok to Pay”更新子記錄(發(fā)票)描述。
//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 } } } }
當(dāng)方法'updateCustomerDescription'被調(diào)用,并且客戶記錄的數(shù)量大于100時(shí),它將達(dá)到SOQL限制。
為了避免這種情況,不要在For循環(huán)中寫(xiě)入SOQL查詢。 在這種情況下,SOQL查詢已經(jīng)寫(xiě)入for循環(huán)。
下面是我們可以避免DML以及SOQL限制的示例。 我們使用嵌套關(guān)系查詢來(lái)獲取發(fā)票記錄,并使用上下文變量trigger.newMap來(lái)獲取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; } }
正如我們?cè)谠S多示例中看到的,我們一直在列表中添加修改的記錄,然后對(duì)該列表執(zhí)行DML操作,而不是對(duì)單個(gè)記錄執(zhí)行DML。 下面是同樣的例子。 這是批量觸發(fā)器以及觸發(fā)器幫助器類模式的示例。 您必須先保存幫助程序類,然后保存觸發(fā)器。
注意:將以下代碼粘貼到我們之前創(chuàng)建的“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限制以及使用Salesdorce.com Apex開(kāi)發(fā)人員指南。
描述 | 限制 |
---|---|
Total heap size 總堆大小 | 6 MB / 12 MB |
Total number of DML statements issued 發(fā)出的DML語(yǔ)句的總數(shù) | 150 |
Total number of records retrieved by a single SOSL query 單個(gè)SOSL查詢檢索的記錄總數(shù) | 2000 |
Total number of SOSL queries issued 發(fā)出的SOSL查詢的總數(shù) | 20 |
Total number of records retrieved by Database.getQueryLocator Database.getQueryLocator檢索的記錄總數(shù) | 10000 |
Total number of records retrieved by SOQL queries 通過(guò)SOQL查詢檢索的記錄總數(shù) | 50000 |
更多建議: