API
@-Formulas
JavaScript
LotusScript
Reg Exp
Web Design
Notes Client
XPages
 
Proper way to delete documents
Did you know there's a right way and a wrong way to delete documents in LotusScript? We've seen code similar to this too many times:

Set view = db.GetView("DocumentsToDelete")
Set doc = view.GetFirstDocument
While Not doc Is Nothing
   Call doc.Remove(True)
   Set doc = view.GetFirstDocument
Wend

When running through the code, the document is removed and then the handle is refreshed by getting the first document in the view again. This code will work in many instances, but we've seen times when it will get into an infinite loop or generate an error. The problem stems from relying on Domino too much to keep the view index up to date while processing the script.

In the above code, if Domino doesn't update the view index the instant the "Remove" method is called, the next statement will get the same document that was just removed. Trying to remove the document again will cause the agent to fail. We've also seen instances where many updates to the view index in a short period of time (like the code could cause) can corrupt the view index, and the variable "doc" could end up pointing to something that can't be removed, causing an infinite loop.

What's the right way?

The correct way to delete all the documents out of a view follows this sample code:

Set view = db.GetView("DocumentsToDelete")
Set doc = view.GetFirstDocument
While Not doc Is Nothing
   Set nextDoc = view.GetNextDocument(doc)
   Call doc.Remove(True)
   Set doc = nextDoc
Wend

The difference here is that a handle to the next document in the view is established before the first document is deleted. Then the variable pointing to the deleted document is set to point to the next document in the view. With this code, the view index never needs to be updated, although it doesn't hurt if it is updated.

Note that there is still a potential problem with many updates to the index causing the index to become corrupt. However, the difference here is that the script isn't forcing the index to be refreshed. You have a handle to a document and are asking to get the next document in the view. Domino knows that the current document and next document have not been updated, so the current index is not asked to refresh. Once the document is deleted, the next document and the document after that have not changed, so the current index again is not asked to refresh. (Domino will still refresh the index, but on its own schedule instead of on the script's schedule). This really minimizes the chances of causing index corruption.

Incidentally, the NotesDocumentCollection class has a "RemoveAll" method that deletes all the documents in the collection. So let's say that the view given in the examples above has a selection formula of SELECT ToBeDeleted = "1". You could use this code instead of having the view, and achieve the same effect:

Set coll = db.Search({SELECT ToBeDeleted = "1"}, Nothing, 0)
Call coll.RemoveAll(True)

A collection of documents is built using the "Search" method in the NotesDatabase class. Then all those documents are deleted in one statement. This is a pretty efficient way of doing things and you're not relying on a view index at all (the "DocumentsToDelete" view doesn't need to exist). However, we've found that document security causes this method to not work in certain situations. If you have document security (Readers/Authors fields), then test it out to make sure. Without document security, it's a quick bit of code to delete a bunch of documents.