1
votes

I built an application in C# that copies documents from a source NSF to a destination NSF. The destination NSF is an empty shell, retaining all design elements, based on the source NSF. I am using Lotus Notes 8.5.3 and am not connected to a Domino Server.

I use this application to split the source NSF into smaller chunks. The goal is to create destination NSFs that can be handled effectively by our automated (eDiscovery) systems. I need to ensure that as much metadata as possible are preserved.

My existing code meets these goals, except that that (1) I lose foldering information. After copying documents, all folders are empty. (2) All documents are marked as Read, even if they were unread in the source.

Code C#

//Establish session
NotesSession ns = new Domino.NotesSessionClass();
ns.Initialize("");

//Open source NSF
NotesDatabase nd = ns.GetDatabase("", "test.nsf", false);
//Open destination NSF.
//Assume that all design elements of nd2 are identical to those of nd
NotesDatabase nd2 = ns.GetDatabase("", "test2.nsf", false);

//Create view that returns all documents.
NotesView nView2 = nd.GetView("$All");
nd.CreateView("All-DR", "SELECT @ALL", nView2, false);
NotesView nView = NotesConnectionDatabase.GetView("All-DR");

//Loop through entries in the new view
NotesViewEntry nvec = nView.AllEntries;
nve = nvec.GetFirstEntry();

for (int j = 1; j <= intEntryCount; j++)
{
     if (j == 1)
     {
          nve = nvec.GetFirstEntry();
     }
     else
     {
          nve = nvec.GetNextEntry(nve);
     }

     //Copy document to second database.
     NotesDocument ndoc = nd.GetDocumentByUNID(nve.UniversalID);         
     ndoc.CopyToDatabase(nd2);
 }
 //End loop.
 //All documents are copied.

The result is that I end up with a destination NSF that has all the documents copied over. Assume that all the folders are also there. However, none of the documents are in the folders. Every document is marked as read.

How can I fix the folders and unread issue?

2
Since unread marks are tracked by user, have you tried opening those destination database with an ID other than the one used to do the copying to see if the documents show as unread to other users? - David Navarre
I have verified that if an NSF is opened with a different ID file, all documents will appear unread. - Jacob Quisenberry

2 Answers

2
votes

Another thought on moving to folders, especially if the database isn't set up for FolderReferences to work:

You can iterate over the array of NotesView objects obtained from the NotesDatabase object's Views property. Each NotesView has a property that tells you if it is a folder.

Once you know about all the folders, you can iterate within each folder and collect a list of NotesDocuments that are contained within. Then by storing this information in a dictionary you could use this as a lookup while you process each document to decide what folder(s) it needs to be placed in.

Something like this (not tested):

object oViews = nd.Views;
object[] oarrViews = (object[])oViews;
Dictionary<string, List<string>> folderDict = new Dictionary<string, List<string>>();
for (int x=0; x < oarrViews.Length - 1; x++)
{
    NotesView view = viewArray[x];
    if (view.IsFolder) 
    {
        NotesDocument doc = view.GetFirstDocument();
        while (doc != null)
        {
            // Populate folderDict Dictionary by setting
            // document's UNID as Key, and adding folder name to List
        }
    }
}

Then in your loop:

//Copy document to second database.
NotesDocument ndoc = nd.GetDocumentByUNID(nve.UniversalID);  
NotesDocument newDoc = ndoc.CopyToDatabase(nd2);

if (folderDict.ContainsKey(nve.UniversalID)) {
    foreach (var folderName in folderDict[nve.UniversalID]) {
        newDoc.PutInFolder(folderName, true);
    }
}       
5
votes

There is a FolderReferences property in the NotesDocument class in the back-end classes. I'm not 100% sure if that property is exposed in the COM classes and interop for C#, but if it is, you can use that along with the PutInFolder() method to solve part of your problem.

As far as read/unread marks are concerned, the critical question is whether you are concerned only about the read/unread status for yourself, or whether you are trying to preserve it for all users of the database. If you only care about unread marks for yourself, then you might be able to use the getAllUnreadDocuments() method of the NotesDatabase class -- but this requires Notes/Domino 8 or above (on the machine where your code is running), and again I'm not sure if this method (or the NotesNoteCollection class that it returns) is exposed via the COM/interop interface for C#. If it is available, then you can iterate through the collection and use the MarkUnread() method. If you care about unread marks for all users, then I'm not sure if there is a way to do it at all -- but if there is, it's going to require using calls from the Notes C API.