2011-05-03 23 views
1

我在學習Salesforce.com的Apex編程語言,我在這裏有一些代碼來自Jason Ouellette編寫的「Force.com平臺開發」一書。我仍然在學習基礎知識,請耐心等待。爲了將上面的代碼放在上下文中,我們在本書中有一個服務管理器示例應用程序,我正在檢查他們寫的Apex觸發器設備,以確保時間卡具有有效的分配。分配是一個記錄,表示某個資源在某個時間段內在某個項目上配備了人員。顧問(又名資源)只能爲他或她有權工作的項目和時間段輸入時間卡。 Resource_c是Assignment_c和Timecard_c對象的父級。Elementary Apex Trigger Logic Breakdown

所以這裏是他們給我的觸發器和相應的apex類的代碼。 我一直試圖分解它並逐行評論/提問,以便理解它的邏輯。不過,我仍然錯過了一些基礎知識,隨時可以幫助我解讀這一點。

5-57觸發

trigger validateTimecard on Timecard__c (before insert, before update) { 
    TimecardManager.handleTimecardChange(Trigger.old, Trigger.new); 
    // TheApexClass.methodThatDoesWork(variable, variable) 
    // So there are 2 parameters which are 2 lists, Trigger.old and Trigger.new. 
    // Which means, when this method is called it needs these 2 lists 
    // to process it's block of code, right? 
    // Why are they called Trigger.old, Trigger.new? Does the order of variables   matter? 
} 

5-58 - 雍雅軒類 - 這確實驗證代表觸發的考勤卡的工作。

public class TimecardManager { 
     public class TimecardException extends Exception {} 
     public static void handleTimecardChange(List<Timecard__c> oldTimecards, List<Timecard__c> newTimecards) { 

      // Identifying 2 lists of Timecards as parameters, oldTimecards and newTimecards 
      // within the class. How is this associated with the trigger parameters 
      // that were seen in the trigger above. Are they the same parameters with 
      // different names? Why are they named differently here? Is it better to 
      // write the trigger first, or the apex class first? 

      Set<ID> resourceIds = new Set<ID>(); // making a new set of primitive data type ID called resourceIds 

      for (Timecard__c timecard : newTimecards) { 
       // This for loop assigns the timecard variable record to the list of newTimecards 
       // and then executes the block of code below for each. 
       // The purpose of this is to identify all the resources that have timecards. 
       resourceIds.add(timecard.Resource__c); 

       // It does this by adding the Timecard_c's relationship ID from each parent record Resource_c to the resourceIds set. 
       // For clarification, Resource_c is a parent to both 
       // Assignment_c and Timecard_c objects. Within the Timecard_c object, Resource_c 
       // is a Master-Detail data type. Is there a relationship ID that is created 
       // for the relationship between Resource_c and Timecard_c? 
      } 

      List<Assignment__c> assignments = [ SELECT Id, Start_Date__c, End_Date__c, Resource__c FROM Assignment__c WHERE Resource__c IN :resourceIds ]; 

      // The purpose of this is to make a list of selected information from Assignments_c that have resources with timecards. 

      if (assignments.size() == 0) { 
       // If there isn't a Resource_c from Assignments_c that matches a Resource_c that has a Timecard_c, 
       throw new TimecardException('No assignments'); // then an exception is thrown. 
      } 

      Boolean hasAssignment; // creation of a new Boolean variable 
      for (Timecard__c timecard : newTimecards) { // so for every newTimecards records, 
       hasAssignment = false; // set Boolean to false as default, 
       for (Assignment__c assignment : assignments) { // check through the assignments list 
        if (assignment.Resource__c == timecard.Resource__c && // to make sure the Resources match, 
         timecard.Week_Ending__c - 6 >= assignment.Start_Date__c && // the end of the timecard is greater than the assignment's start date, 
         timecard.Week_Ending__c <= assignment.End_Date__c) { // and the end of the timecard is before the assignment's end date. 
          hasAssignment = true; // if these all 3 are correct, than the Timecard does in fact have an assignment. 
          break; // exits the loop 
        } 
       } 
       if (!hasAssignment) { // if hasAssignment is false then, 
        timecard.addError('No assignment for resource ' + // display an error message 
        timecard.Resource__c + ', week ending ' + 
        timecard.Week_Ending__c); 
       } 
      } 
     } 
    } 

謝謝你的幫助。

回答

2

1.什麼是Trigger.old/Trigger.new:?

Trigger.new/Trigger.old是靜態集合,可用於在觸發器上下文中運行的任何Apex代碼,即可直接在觸發器或觸發器調用的任何類中觸發。

Apex甚至會爲您提供Trigger.newMap和Trigger.oldMap,它返回一個Map而不是sobject列表。

這些集合的唯一目的取決於在哪個事件中觸發了觸發器,例如,如果事件是「插入前」或「插入後」,Trigger.old將沒有意義,因此不可用。 Trigger.old通常用於比較記錄更新期間所做的更改。

2.是否爲了事項:只取決於你的邏輯,在這種考勤管理情況下,作爲方法「handleTimecardChange」之前新老預計考勤卡,所以你需要通過Trigger.old作爲第一個參數。

3.是否需要列表? :同樣取決於你的實現,Trigger.new/old返回一個列表,其中sobject是寫入觸發器的列表。它也不是要傳遞Trigger.new/old作爲參數,而是保持Apex類與Trigger上下文分離的良好實踐。它使單元測試更容易。

希望這有助於閱讀Apex語言參考,以便更深入地瞭解Apex語言。 Jason O.書很棒,但你需要首先理解基礎知識。 這裏是鏈接到的Apex語言參考:http://www.salesforce.com/us/developer/docs/apexcode/index.htm

0

觸發的newnewMapoldoldMap僅可根據DML的要跟蹤的類型。

DELETE =僅舊可用

INSERT =只有新的可用

UPDATE =新舊是可用的並且在列表中的條目的順序是匹配(例如,新[1]替換舊[ 1])。 new包含新值,old包含舊值(但ID始終相同),因此您可以比較並檢查某個字段是否發生更改。

你應該總是把新/舊視爲多項列表(或映射爲* Map)。永遠不要假設只有一個條目,就像使用常規SQL一樣,批量更新操作只會在給你一個新舊列表的列表時觸發一次觸發器。您必須迭代所有更改的行並應用您擁有的任何邏輯。

在這個例子中,oldTimecards參數在靜態方法中根本沒有被使用,因此它根本不需要被引用。很可能這也浪費了資源,因爲SF不必使用它就可以構建一個完整的列表(儘管不知道它們是否優化了它)。由於您控制觸發代碼和支持類代碼,所以只會傳遞您所需的內容。