[Notes/Domino] 文書を取得するメソッドの動作の違いについて
この記事はちょっとニッチすぎるかなと思って書くつもりは無かったのですが、去年同じことで小一時間ほど悩んだことがあったので、自戒をこめてエントリ。今回はいつもと趣向を変えて、クイズ形式にします(^^;
問題
以下のスクリプトを実行した場合、ビューの最初の文書の FieldA、FieldB、FieldC の値がそれぞれどうなるか、またその理由について述べてください。
加えて、「vw.GetFirstDocument()」を「vw.GetDocumentByKey("FrmTest", True)」に変えた場合にどうなるかについても述べてください。
Dim ss As New NotesSession Dim db As NotesDatabase Dim vw As NotesView Dim col As NotesDocumentCollection Dim doc As NotesDocument Set db = ss.CurrentDatabase Set vw = db.GetView("VwTest") Set col = vw.GetAllDocumentsByKey("FrmTest") Set doc = vw.GetFirstDocument() doc.FieldA = "1" Call doc.Save(True, True) Call col.StampAll("FieldB", "1") Set doc = vw.GetFirstDocument() doc.FieldC = "1" Call doc.Save(True, True)
<前提条件>
- VwTest ビューは、FrmTest フォームの文書を表示し、第1列目がフォーム名("FrmTest")でソートされています。ビューには複数の文書が表示されています。
- 処理実行前、FieldA、FieldB、FieldC はそれぞれ NULL です。
- DBはサーバー上にあり、クライアントからの実行とします。
- 動作確認は R6.5.4 で行いました(たぶん全バージョン同じだと思いますが)。
- このような処理を書くことの是非についてはくれぐれも追及しないでください(^^; あくまで問題をシンプルにするためのスクリプトです。
答え(反転させてください)
(結果)GetFirstDocument の場合は、FieldA = "1"、FiledB = ""、FieldC = "1" となり、GetDocumentByKey の場合は、FieldA = "1"、FiledB = "1"、FieldC = "1" となります。ビューの最初の文書以外の文書は、いずれの場合でも、FieldA = ""、FieldB = "1"、FieldC = "" となります。
(理由)GetFirstDocument はメモリ上に以前取得した文書オブジェクトが残っていたら、再利用します。StampAll はメモリ上に文書オブジェクトを展開する処理ではないので、ローカルPCのメモリの値は書き換わりません。最後の3行で、以前のオブジェクトが取得され、それがサーバーに反映されるため、StampAll が無視された格好になります。GetDocumentByKey の場合は、常に最新のオブジェクトを取得するので、そのようなことは起こりません。
全部試したわけではないですが、常に最新のオブジェクトを取得するのは、GetDocumentByKey だけのようです。GetNthDocument、db.GetDocumentByID なども、再利用するタイプみたいです。
ちなみに、StampAll を RunOnServer に変えて、サーバー上で文書を書き換えるエージェントを実行した場合も、同様の結果となります。ローカルPCのメモリは書き換わりませんので。
(解決策)最後の GetFirstDocument の前に、「Delete doc」の1文を入れるだけです。これで以前取得した文書オブジェクトが破棄され、最新の値が取得されます。「Set doc = Nothing」では、オブジェクトへの参照を切るだけで、オブジェクトの破棄はガーベジコレクタが動作するまで実行されませんので不正解です。
コメント
コメントはありません
※コメントは承認制となっております。管理者が承認するまで表示されません。申し訳ありませんが、投稿が表示されるまでしばらくお待ちください。