2011-05-03 53 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不必使用它就可以构建一个完整的列表(尽管不知道它们是否优化了它)。由于您控制触发代码和支持类代码,所以只会传递您所需的内容。