
お久しぶりです、全然(blog)書かないkudoです。
本日は案件内で便利さを実感したFor Eachでのトランザクション指定、DataProviderでのFrom句についてご紹介します。
この機能、実はEv3から追加された機能で便利そうだとは思っていたのですが・・・
今まで携わっていた案件がEv2どまりだったため使う機会がありませんでした。
しかし、直近の案件でGx15を使う事となり改めてこの機能の便利さを実感できたのでご紹介します。
まず、For Each等とタイトルに記載しているのは
For EachとDataProviderで記述方法が異なるためです
For Eachの場合は
1 2 3 4 5 |
For Each Transaction_A Order SortColumn Where Daet >= #2019/01/02# /* ソースコード */ EndFor |
DataProviderの場合は
1 2 3 4 5 6 7 8 9 10 |
SDT_Collection From Transaction_A Order SortColumn Where Daet >= #2019/01/02# { SDT_Item { /* ソースコード */ } } |
という書き方になります
For Eachのコードをみて気になった方もいるかと思いますが
Ev2までは
1 2 3 4 |
For Each SortColumn Where Date >= #2019/02/01# /* ソースコード */ EndFor |
とFor Eachの後に項目属性を記述することで、Order句無しでソートが実行される仕様でしたが
Ev3からはトランザクションの指定が増えたことに伴い、ソートする場合はOrder節が必須となっています。
しかし、トランザクションの指定はこのような些細な変化を帳消しにするような利点を持っています。
GeneXusは推論エンジンを利用し、SQLを自動生成するという特性上
トランザクションの作り方によってはFor Eachをネストした場合に望んだテーブルを参照できない場合が発生します。
その場合、DefinedByやOrder、Uniqueを利用し調整しますが
稀にそれだけでは望むテーブルが参照されず、泣く泣くサブルーチンや別オブジェクトに変更し、実装していました。
しかし、トランザクションを指定できるようになったことで
DefinedByやOrder、Uniqueより強力にトランザクションを指定できるようになり
今までサブルーチンなどで記載していたところをネストした形で記述できるようになりました。
以降、どのように変わるのかFor Eachを例にご紹介します。
Ev2までの記述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
For Each Order C_Date &Date = C_Date Do 'Sub_TranNotify' EndFor Sub 'Sub_TranNotify' For Each Order (N_Date) Where N_Date <= &Date /* ソースコード */ EndFor EndSub |
Ev3からの記述
1 2 3 4 5 6 7 8 9 10 11 |
For Each TranCalendar Order C_Date For Each TranNotify Order (N_Date) Where N_Date <= C_Date /* ソースコード */ EndFor EndFor |
トランザクションを指定する方法をとると、ソースコードを減らせるだけでなく
項目ごとの関連も見やすくなります。
また、あくまで体感の話になりますが
後者の書き方をした方がレスポンスが早く感じたため
おそらくSQLも1つに纏められているのだと思われます。(検証不足で申し訳ありません)
さらに副次的な効果としてビルド時間の短縮があります。
これは、For Eachごとにベースとなるトランザクションを指定するため、通常行われるFor Each内の項目属性からのベーステーブルを推論する処理が大幅に軽減され
その結果、ジェネレートにかかる時間が短くなり発生する効果です。
しかし、Ev3からの割と新しい変化だったためか、この便利な仕様を利用している案件が少ないように感じます。
ビルド時間やレスポンスに苦労している人は一度トランザクションの指定で改善できないか試してみてはいかがでしょうか?