今回は思い出したくない過去の失敗事例を思い出してしまったので、ここにご紹介します。
変換前の式には @DbLookup は下のような式です。
Category2 := @DbLookup("": "NoCache"; @DbName; "test"; Category1; "Category2")
これを Lotus Script へ変換するとします。Category1 はフィールド名です。
Dim ws As New NotesUIWorkspace Dim doc As NotesDocument Dim vw As NotesView Dim dc As NotesDocumentCollection Dim category2 As Variant Dim tmpKey As String, init(0) As String Set vw = ws.CurrentDatabase.Database.GetView( "test" ) set tmpKey = ws.CurrentDocument.Document.Category1(0) Set dc = vw.GetAllDocumentsByKey( tmpKey, True ) If dc.Count > 0 Then category2 = init Set doc = dc.GetFirstDocument While Not ( doc Is Nothing ) Category2 = Arrayappend( Category2, doc.Category2 ) Set doc = dc.GetNextDocument( doc ) Wend category2 = Fulltrim( Category2 ) End If一見何の問題ないように見えるこのプログラム...実は大きな落とし穴があったんです。
見落としだったのですが...フォーム上の Category1 は"複数値も可"が有効なフィールドでした。
@DbLookup のキーには複数値を設定できます。
複数値で検索した場合、指定した複数の値に一致するすべての値を一度に取り出します。
そのため上記の Category(0) といったように配列の0番目だけを取り出すのではなく、
配列のすべての要素を検索のキーとして指定する必要があります。
ここで注意したいのは、GetAllDocumentsByKey で指定するキーです。
このキーは配列でもよいのですが、@DbLookup では最初のソートされた列だけを対象に検索してくれるのに対して、GetAllDocumentsByKey では複数のソート列を対象にして検索します。
同じように複数値を指定しても検索結果が違うのです。
つまり、次のように変換するのが正しかったのです。
<...宣言は省略...> Set vw = ws.CurrentDatabase.Database.GetView( "test" ) Category2 = init Forall o In ws.CurrentDocument.Document.Category1 Set dc = vw.GetAllDocumentsByKey( o, True ) If dc.Count > 0 Then Set doc = dc.GetFirstDocument While Not ( doc Is Nothing ) Category2 = Arrayappend( Category2, doc.Category2 ) Set doc = dc.GetNextDocument( doc ) Wend End If End Forall Category2 = Fulltrim( Category2 )
ソボクな疑問
返信削除Set vw = ws.CurrentDatabase.Database.GetView( "test" )
の部分は、
set db = ws.CurrentDatabase
set vw = db.getview("test")
と書く場合もあるとおもうのですが、dbを再利用する場合、
実行パフォーマンス上"set db"しておいた方が良いのか、
"set db"していなくても変わらないのかご存じですか?
基本的すぎて、申し訳ないのですが...
体感速度を重視するなら、ほとんど変わらないと思います。
返信削除ただ(計ったことがないのでよくわかりませんが)db オブジェクトを新規に作成する場合、それだけメモリを消費すると仮定した場合、"set db" しないほうがパフォーマンスはいいかもしれませんね。
機会があればエージェント・プロファイルで調べてみたいと思います。