DXブログ
GeneXusにおけるNewコマンド・For Eachコマンドによる登録・更新
🍁
大串
開発の大串と
🌰
辛島
開発の辛島です
🍁
大串
今回は私たちがGeneXus開発で最初につまずいた
Newコマンド・For Eachコマンドによる登録・更新について振り返ります!
Newコマンド・For Eachコマンドによる登録・更新について振り返ります!
環境:GeneXus18、WorkWithPlus(WWP)、Tomcat 10.1使用
Newコマンドによる登録
🍁
大串
まずは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);
🌰
辛島
実際に実行した結果このように購入履歴テーブルにデータが登録されます
【登録内容】
【実行結果】
🍁
大串
ここで注目すべきは入力内容が
・必須項目「ユーザーID」が入力されている
・「商品ID」(外部参照項目)が「商品リスト」テーブルに登録済みのIDである
を満たしている、という点です
これを満たしていないとどうなるのか、、、試してみましょう
・必須項目「ユーザーID」が入力されている
・「商品ID」(外部参照項目)が「商品リスト」テーブルに登録済みのIDである
を満たしている、という点です
これを満たしていないとどうなるのか、、、試してみましょう
エラーチェックの重要性
🍁
大串
まずは必須項目を入力しなかった場合を試してみます
■必須項目を入力しなかった場合
【登録内容】
【実行結果】
🍁
大串
必須項目の箇所が空白にもかかわらず、そのまま登録されてしまいます
※これはNewコマンドの「Rulesが効かない」(例えば、Patternsの「Is required」(必須項目)の設定が効かない)という特徴が原因です
※これはNewコマンドの「Rulesが効かない」(例えば、Patternsの「Is required」(必須項目)の設定が効かない)という特徴が原因です
🌰
辛島
ということは、外部参照項目に登録されていない値を入力した場合も、言わずもがなですね、、
■外部参照項目に登録されていない値を入力した場合
【実行結果】
🌰
辛島
この場合は存在しない値を設定したことで500エラーが出ていますね
🍁
大串
ここまでくると更新した場合も気になりますね!
■更新をした場合
【登録内容】
【実行結果】
🍁
大串
予想通り更新されませんでした😅
これが最初の機能説明で「新規登録」を強調していた理由ですね
これが最初の機能説明で「新規登録」を強調していた理由ですね
エラーハンドラー
🍁
大串
ここまでに確認してきた通り、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 ルール
このようにキー項目の重複チェックや外部参照項目のチェックを行ってくれます!
ただしアプリケーション側でのチェック(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コマンド」です
「あれ?更新チェックは入れないの?」と思われたかもしれませんが、大丈夫です!!
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側で発生するエラーしかチェックできないため、コード内にもエラーチェック処理を入れる
例)必須項目チェック、外部参照項目のチェックなど
が重要な点ですね
・NewコマンドとFor Eachコマンドを組み合わせて使用することで登録・更新が行える
・エラーハンドラーはDB側で発生するエラーしかチェックできないため、コード内にもエラーチェック処理を入れる
例)必須項目チェック、外部参照項目のチェックなど
が重要な点ですね
🍁
大串
注意点はありますが便利な機能なので、これらのことに注意しながらコードに組み込んでいきたいですね✨
GeneXus, ローコード開発