yujiroのプログラミング

勉強内容をアウトプットし、サボらないようにする為のブログ

<DAY215>もう一度トリガーについて

\ Follow me!! /

●9/24(火)
●学習日数 215日
●学習時間(本日)6時間
●累計学習時間 914.0時間
●一日あたりの平均学習時間 4.28時間

f:id:yujiro0320:20190904163314p:plain

beforeとafterの違い


before はトリガの実行が先。実行後にシステムによって保存されます。DML の挿入または更新操作を明示的にコールせずに、トリガのレコードを変更できる。
これらのレコードに DML ステートメントを実行すると、エラーが表示されます。

DB保存後にトリガー実行させるafterの場合は明示的なDML操作が必要。
ややこしいので、
SOQLでクエリを引っ張ってる時はafterとの認識で間違いないと思っている。
この時に重要なのがこのDML操作をforループ内で行わない事。ガバナ制限がかかり、エラーとなる可能性が高い。
そのため、以下のような記述が一般的となる。

 List<Task> hoges = new List<Task>();
    for(Opportunity a : trigger.new){
        hoges.add(new Task(Subject='Follow UP Test Task',
                                               WhatId=a.Id)); 
                      System.debug(a.Probability);            
    }

//forから外しておく
     insert hoges;

トリガーで迷った結論できないと判断したこと。

(1)リレーションを使ってコンテキスト変数経由でデーターを引っ張ること。

取引先オブジェクトに入っている項目を使う場合(できる)
for(Account a : Trigger.New) {
        //従業員の数が10人以上なら
        if (a.NumberOfEmployees >10) {
            oppList.add(new Opportunity(Name=a.Name + ' Opportunity',
                                       StageName='Prospecting',
                                       CloseDate=System.today().addMonths(1),
                                       AccountId=a.Id));
        }           
    }
取引先責任者オブジェクトに入っている項目を使う場合(できない)

紐付けでデーター取れるのかなと思ったけど無理。

取り出せたデーター(できる)
 //数値
   if (a.NumberOfEmployees >10)

 //テキスト()
   if (a.AccountNumber =='aaa') 
  
  //選択リスト
  if (a.Type =='Prospect')

  //チェックボックス
  if (a.check__c ==true)
 
 //通貨
 if (a.AnnualRevenue ==111)

 //日付 dateクラスを参照
 if (a.SLAExpirationDate__c.day() == 21)

  //電話 任意の文字列を受け取り、数値を返す
  if (a.Phone == '555-555-5555') 

  //コンテンツ 文字列で受け取る
  if (a.TickerSymbol == '555-555-5555')
取り出せないデーター(できない)
参照関係があるかどうかなど。
もし参照関係が空白ならばとかは無理。

mapを使う事例

IDに紐づいているかどうかを確認するために必要である。

(1)レコードに紐づいている、IDの数を数えて、件数を数えたい時。
(2)商談のIDとタスクのIDをSELECTで取り出す。(商談オブジェクトから)
(3)IDをバインド変数を用いてtirgger.newとバインドさせる。

レコードを繰り返しチェックしていくわけだが、そのIDと紐づいているかをみるためにMapが必要。
Listだとこれはできない。

    Map<Id,Opportunity> oppsWithOpps = new Map<Id,Opportunity>(
            [SELECT Id,(SELECT Id FROM tasks) FROM Opportunity WHERE Id IN :Trigger.New ]);
        
          for(Opportunity a : Trigger.New) {

//生成したレコードのIDを取り出し数が0かどうかを見ている。(関連データーがない事を見ている)
              if(oppsWithOpps.get(a.Id).Tasks.size() == 0){