What is the most efficient way of retrieving a single item from Outlook (interop)
c#, interop, outlook
Solution
Outlook 2007+ added `Folder.GetTable` which optimizes the retrieval using a lightweight approach in comparison to `Folder.Items`. Using Tables can be up to 10x faster than an Items iterator.
As for retrieving the actual item, `Session.GetItemFromID` is the fastest way to retrieve an item - especially if you pass in the `Store.StoreID` as a secondary parameter so Outlook doesn't have to determine which Store a particular `EntryID` belongs to.
const string PR_STORE_ENTRYID = "http://schemas.microsoft.com/mapi/proptag/0x0FFB0102";
Outlook.Table tasks = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderTasks).GetTable();
tasks.Columns.Add(PR_STORE_ENTRYID); // optimal for GetItemFromID
while (!tasks.EndOfTable)
{
Outlook.Row task = tasks.GetNextRow();
Outlook.TaskItem item = Application.Session.GetItemFromID(task["EntryID"], task.BinaryToString(PR_STORE_ENTRYID)) as Outlook.TaskItem;
}
As for best approach - you should track the Task EntryID and Task StoreID in the application if you wanted to minimize sync execution time. Otherwise, the brute force approach of retrieving all tasks would work, but I'd recommend using `Folder.GetTable()` instead of using `Folder.Items`.
Problem
I need to create a program that synchronizes it's own task objects to tasks in outlook. During the operation, tasks in outlook may be created/updated/deleted. The most straightforward way is to iterate over all task items in outlook, looking for which ones to update. Very roughly: ``` ApplicationClass _app; NameSpace _nameSpace; MAPIFolder _folder; _app = new ApplicationClass(); _nameSpace = _app.GetNamespace("MAPI"); _folder = _nameSpace.GetDefaultFolder(OlDefaultFolders.olFolderTasks); Dictionary<int,MyTask> data = GetData(); for (int i = 1; i <= _folder.Items.Count; i++) { TaskItem taskItem = (TaskItem)_folder.Items.Item(i); int itemID; if(ItemNeedsProcessing(taskItem, out itemID)) UpdateItem(taskItem, data[itemID]); } ``` But this could possibly iterate through hundreds of items (depending on the client's outlook task history), just to make one or two changes. Alternatively, I could track the `ItemID` of the task... ``` string itemID = "00000000873..."; //taken from property on object. object o = _nameSpace.GetItemFromID(itemID); //ignore possible exceptions for now TaskItem taskItem = (TaskItem)o; ``` ... and update it directly (which complicates the creation/deletion of tasks on the application side somewhat). Is retrieving the task item directly (`GetItemFromID`) the most efficient way? Or is there some pitfall I'm missing?