DXブログ

TOP > DXソリューション > DXブログ

GeneXusにおけるNewコマンド・For Eachコマンドによる登録・更新

🍁

大串

開発の大串と

🌰

辛島

開発の辛島です

 

🍁

大串

今回は私たちがGeneXus開発で最初につまずいた
Newコマンド・For Eachコマンドによる登録・更新について振り返ります!

環境:GeneXus18、WorkWithPlus(WWP)、Tomcat 10.1使用

Newコマンドによる登録

🍁

大串

まずはNewコマンドについて、振り返って何か印象に残っていることはありますか?

🌰

辛島

エラーチェックを忘れて、うまくいかないことがあったなぁ。。。

🍁

大串

確かに!Newコマンドを使用する際はエラーチェックが大切ですからね😅
ではエラーチェックの重要性などを順に再確認していきましょう

Newコマンドの動き

🍁

大串

まずはNewコマンドの機能について、”New”ということで機能はデータの「新規登録」です
この「新規」というところが重要なポイントです!
また、Newコマンドはプロシージャーでのみ使用が可能なので、シチュエーションとしては自作のウェブパネルからデータの登録・更新を行うときなどに使用します。

🌰

辛島

さっそく実際に簡潔なコードで動きを確認していきましょう!
「購入履歴」テーブルに「購入履歴登録・更新」画面から実行ボタンを押下するとデータが登録される、という流れで見ていきます
また、「購入履歴」は「商品リスト」テーブルの項目を含む(外部参照あり)想定になっています

【購入履歴テーブル】
購入履歴テーブル構成

※1:「ユーザーID」は必須項目です(上図Patterns参照)

※2:「商品ID」が「商品リスト」テーブルを参照している外部参照項目になっています

【商品リスト】
商品リスト登録内容

※「商品リスト」には上図のデータがすでに登録されています

【購入履歴登録・更新画面】(ウェブパネル ※プロシージャー呼び出し元)

購入履歴登録・更新画面

  
//実行ボタン押下時の処理
Event 'DoBtnEnter'

  //更新・登録用プロシージャーの呼び出し
  PRO_PurchaseHistoryAddUpdate.Call(&User_id,&Item_id,&Item_count)
    Commit

EndEvent
  

【プロシージャー内容】

  
●Source記載内容
//Newコマンドによる新規登録
New
  User_id = &User_id
  Item_id = &Item_id
  Item_count = &Item_count
EndNew

ーーーーーーーーーーーーーーーーーーーーーー
●Rules記載内容
parm(in:&User_id,in:&Item_id,in:&Item_count);
  
🌰

辛島

実際に実行した結果このように購入履歴テーブルにデータが登録されます

【登録内容】
入力内容_正常
【実行結果】
データ確認(Newコマンドのみ_エラーチェック無し_存在するコード使用)

🍁

大串

ここで注目すべきは入力内容が
・必須項目「ユーザーID」が入力されている
・「商品ID」(外部参照項目)が「商品リスト」テーブルに登録済みのIDである
を満たしている、という点です
これを満たしていないとどうなるのか、、、試してみましょう

エラーチェックの重要性

🍁

大串

まずは必須項目を入力しなかった場合を試してみます

■必須項目を入力しなかった場合
【登録内容】
入力内容_必須項目なし
【実行結果】
データ確認(Newコマンドのみ_エラーチェック無し_必須項目なし)

🍁

大串

必須項目の箇所が空白にもかかわらず、そのまま登録されてしまいます
※これはNewコマンドの「Rulesが効かない」(例えば、Patternsの「Is required」(必須項目)の設定が効かない)という特徴が原因です

🌰

辛島

ということは、外部参照項目に登録されていない値を入力した場合も、言わずもがなですね、、

■外部参照項目に登録されていない値を入力した場合
入力内容_エラー
【実行結果】
500エラー

🌰

辛島

この場合は存在しない値を設定したことで500エラーが出ていますね

🍁

大串

ここまでくると更新した場合も気になりますね!

■更新をした場合
【登録内容】
入力内容_更新不可
【実行結果】
データ確認(Newコマンドのみ_エラーチェック無し_更新不可)

🍁

大串

予想通り更新されませんでした😅
これが最初の機能説明で「新規登録」を強調していた理由ですね

エラーハンドラー

🍁

大串

ここまでに確認してきた通り、Newコマンドのみでは
「必須項目や外部参照項目のチェック・更新処理」はできませんでした
これらのチェックを行う方法として「エラーハンドラー」があります

【購入履歴登録・更新画面】

  
//実行ボタン押下時の処理
Event 'DoBtnEnter'

  //更新・登録用プロシージャーの呼び出し
  PRO_PurchaseHistoryAddUpdate.Call(&User_id,&Item_id,&Item_count,&IsError)
    //エラーがなければコミット
    If &IsError = False
      Commit
    Else
      Rollback
    EndIf

EndEvent
  

【プロシージャー内容】

  
●Source記載内容

//変数の初期化
&IsError = False

//Newコマンドによる新規登録
New
  User_id = &User_id
  Item_id = &Item_id
  Item_count = &Item_count
EndNew

//エラーハンドラー
Sub 'DBerror'
    &IsError = True
    &gxErrOpt = 0
    Msg(&gxDBtxt)
EndSub

ーーーーーーーーーーーーーーーーーーーーーー
●Rules記載内容
parm(in:&User_id,in:&Item_id,in:&Item_count,out:&IsError);
error_handler('DBerror');
  

【実行結果】
エラーハンドラーあり(重複チェック)

🍁

大串

エラーハンドラーはDB側で発生するエラーに対してチェックを行うため、
このようにキー項目の重複チェックや外部参照項目のチェックを行ってくれます!
ただしアプリケーション側でのチェック(Patternsで設定する必須項目のチェックなど)はできないので注意です!!
(参考)Error_Handler ルール

🌰

辛島

つまり、エラーハンドラーはあくまでDBまで到達してからのエラーチェック、いわば「最後の砦」なので、エラーハンドラーだけでなく、コード内でもエラーチェック処理を入れる(アプリケーション側でエラーチェックを行う)のがベスト!ということですね!!

エラーチェックの実施

🌰

辛島

ということで、エラーチェックを入れたのがこちらです🧑‍🍳

  
●Source記載内容

//変数の初期化
&IsError = False

//必須項目確認
If &User_id.IsEmpty()
	Msg(!"ユーザーIDは必須項目です")
	&IsError = True
EndIf

//外部参照項目が存在するか確認
For Each ItemList
    Where Item_id = &Item_id
    Exit
When None
    Msg(!"入力された商品IDは登録されていません")
    &IsError = True
EndFor

If &IsError = False
    //エラーがない場合
    //Newコマンドによる新規登録
    New
      User_id = &User_id
      Item_id = &Item_id
      Item_count = &Item_count
    EndNew
EndIf

//エラーハンドラー
Sub 'DBerror'
    &IsError = True
    &gxErrOpt = 0
    Msg(&gxDBtxt)
EndSub

  

【実行結果】
必須項目確認_成功

🌰

辛島

このように、コードに追加したエラーメッセージが表示されるようになります
「あれ?更新チェックは入れないの?」と思われたかもしれませんが、大丈夫です!!
Newコマンドにあるコマンドを組み合わせると更新を可能にすることができます!
それが「For Eachコマンド」です

For Eachコマンド

🍁

大串

こちらも料理番組形式でさっそく完成したコードをお見せします🧑‍🍳

  
●Source記載内容


//変数の初期化
&IsError = False

//必須項目確認
If &User_id.IsEmpty()
    Msg(!"ユーザーIDは必須項目です")
    &IsError = True
EndIf

//外部参照項目が存在するか確認
For Each ItemList
    Where Item_id = &Item_id
    Exit
When None
    Msg(!"入力された商品IDは登録されていません")
    &IsError = True
EndFor

If &IsError = False
    //エラーがない場合
    //For eachコマンドによる更新
    For Each PurchaseHistory
      Where User_id = &User_id
      Item_id = &Item_id
      Item_count = &Item_count
    When None
      //Newコマンドによる新規登録
      New
        User_id = &User_id
        Item_id = &Item_id
        Item_count = &Item_count
      EndNew
    EndFor
EndIf

//エラーハンドラー
Sub 'DBerror'
    &IsError = True
    &gxErrOpt = 0
    Msg(&gxDBtxt)
EndSub

  

【更新内容】
更新内容

【実行結果】
■更新前
更新前
■更新後
更新後

🍁

大串

For Eachコマンドと組み合わせたことで更新もできるようになりました!

まとめ

🍁

大串

改めて振り返ると気を付ける点が多い処理ですよね🤔

🌰

辛島

振り返った内容をまとめると、
・NewコマンドとFor Eachコマンドを組み合わせて使用することで登録・更新が行える
・エラーハンドラーはDB側で発生するエラーしかチェックできないため、コード内にもエラーチェック処理を入れる
例)必須項目チェック、外部参照項目のチェックなど
が重要な点ですね

🍁

大串

注意点はありますが便利な機能なので、これらのことに注意しながらコードに組み込んでいきたいですね✨

Tag Icon GeneXus, ローコード開発