我正在尝试学习Salesforce.com的Apex编程语言,我在这里有一些代码示例来自Jason Ouellette的“使用Force.com平台开发”一书。我还在学习基础知识所以请耐心等待。要将此代码放在上下文中,整个书中都有一个服务管理器示例应用程序,我正在检查他们编写的Apex触发器设备,以确保时间卡具有有效的分配。赋值是指示资源在某个时间段内在项目上配备的记录。顾问(也称为资源)只能为他或她有权工作的项目和时间段输入时间卡。 Resource_c是Assignment_c和Timecard_c对象的父级。
所以这里是他们为触发器和相应的顶点类提供的代码。 我一直试图将其分解并逐行评论/提问以理解其逻辑。但是,我仍然缺少一些基础知识,请随时帮我解读。
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 - Apex类 - 负责代表触发器验证时间卡。
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);
}
}
}
}
感谢您的帮助。
答案 0 :(得分:2)
<强> 1。什么是Trigger.old / Trigger.new:?
Trigger.new/Trigger.old是可用于在Trigger上下文下运行的任何Apex代码的静态集合,即直接在触发器或Trigger调用的任何类中触发。
Apex甚至会为您提供Trigger.newMap和Trigger.oldMap,它返回Map而不是sobject列表。
这些集合的唯一目的取决于触发器触发的事件,例如,如果事件是“插入之前”或“插入之后”,则Trigger.old将没有意义,因此不可用。 Trigger.old始终用于比较记录更新期间完成的更改。
<强> 2。顺序是否重要:这只取决于你的逻辑,在这个Timecard管理器的情况下,因为方法“handleTimecardChange”在new之前需要旧的时间卡,所以你需要将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
答案 1 :(得分:0)
触发器的new
,newMap
,old
和oldMap
仅可用,具体取决于您要跟踪的DML类型。
DELETE =只有旧版
INSERT =只有新的可用
UPDATE =旧的和新的都可用,列表中的条目顺序是匹配的(例如new [1]替换旧的[1])。 new包含新值,old包含旧值(但ID始终相同),因此您可以比较并检查某个字段是否已更改。
您应该始终将new / old视为多条目列表(或* Map的映射)。永远不要假设只有一个条目,就像常规SQL一样,批量更新操作只会在给出新旧行列表时调用触发器。您必须遍历所有已更改的行并应用您拥有的任何逻辑。
在此示例中,静态方法中根本没有使用oldTimecards参数,因此根本不需要引用它。很可能它也浪费了资源,因为SF必须在没有你使用它的情况下构建一个完整的旧列表(但是,不确定它们是否完全优化它)。由于您可以控制触发器代码,并且支持类代码仅传递您所需的内容。