I have been attempting to resolve this issue for about two weeks now. So far, everything I try has a problem that makes it unworkable.
Problem
One of the current requirements is that I need to be able to transfer calendar events from multiple site collections into a single, amalgamated merged calendar stored on an entirely separate collection.
To that end, I have downloaded and installed Useful Sharepoint Designer Custom Workflow Activities from CodePlex, which adds extra workflow options for SPD. One of these allows you to copy a list item to another list at another URL. Ok, great. Easy enough to dump all the items we need into the alagamated calendar, just use the workflow to copy it whenever a new item is created or modified.
The problem I'm running into now is that the amalgamated calendar starts accruing duplicates, as every time an item is copied, it does not overwrite the original. To that end, I've created a sequential workflow in Visual Studio that just iterates through the events, and deletes old ones based on their original IDs. Running this manually works fine; I'm left with just the latest versions of events.
Since the copy process uses the System Account, the new item in the amalgamated site collection will not trigger any item creation workflows, to prevent workflow recursion. Alright, I understand that, and try to work around that.
I have tried adding the workflow as a timer job, in order to trigger this workflow on a regular basis. I have tried just creating a permanent whileActivity loop, that doesn't end unless it gets cancelled or triggers a fault. The other addition is a delayActivity, which pauses after iterating through the list, and then just dumps it back to the top of the loop. The idea is to start the workflow manually, and let it go. Unfortunately, the first time works fine, and when the workflow starts again, I get an error: Object reference not set to an instance of the object.
I have also tried using EFWorkflowTimer, to trigger workflows at specific times. I get the same error message as above: Object reference not set to an instance of the object.
This leads me to believe that there is something in my code that doesn't parse properly when disassociated from manual execution.
My Code:
SPWorkflow.CreateHistoryEvent(workflowProperties.Web, this.WorkflowInstanceId, 0, workflowProperties.Web.CurrentUser, new TimeSpan(), "", "Beginning Checking for Duplicates", "");
using (SPWeb web = workflowProperties.Web)
{
SPList list = web.Lists[workflowProperties.ListId];
SPWorkflow.CreateHistoryEvent(workflowProperties.Web, this.WorkflowInstanceId, 0, workflowProperties.Web.CurrentUser, new TimeSpan(), "", "Looping through events", "");
List<SPListItem> itemsToDelete = new List<SPListItem>();
foreach (SPListItem item in list.Items)
{
SPWorkflow.CreateHistoryEvent(workflowProperties.Web, this.WorkflowInstanceId, 0, workflowProperties.Web.CurrentUser, new TimeSpan(), "", "Current Item: " + item["ID"], "");
foreach (SPListItem search in list.Items)
{
if (item["OriginalID"].Equals(search["OriginalID"]) && !item["ID"].Equals(search["ID"]))
{
SPWorkflow.CreateHistoryEvent(workflowProperties.Web, this.WorkflowInstanceId, 0, workflowProperties.Web.CurrentUser, new TimeSpan(), "", "Duplicate found. Description: " + item["Description"], "");
if ((DateTime)item["Created"] > (DateTime)search["Created"])
{
SPWorkflow.CreateHistoryEvent(workflowProperties.Web, this.WorkflowInstanceId, 0, workflowProperties.Web.CurrentUser, new TimeSpan(), "", "Deleting Item: " + search["ID"], "");
if (!itemsToDelete.Contains(search))
itemsToDelete.Add(search);
}
else
{
SPWorkflow.CreateHistoryEvent(workflowProperties.Web, this.WorkflowInstanceId, 0, workflowProperties.Web.CurrentUser, new TimeSpan(), "", "Deleting Item: " + item["ID"], "");
if (!itemsToDelete.Contains(item))
itemsToDelete.Add(item);
}
}
}
}
foreach (SPListItem currentItem in itemsToDelete)
{
currentItem.Delete();
}
SPWorkflow.CreateHistoryEvent(workflowProperties.Web, this.WorkflowInstanceId, 0, workflowProperties.Web.CurrentUser, new TimeSpan(), "", "Check for duplicates complete", "");
}
When I check my workflow history, I see:
7/19/2012 11:19 AM System Account Creating and Invoking Duplicate Workflow
7/19/2012 11:19 AM System Account Beginning Checking for Duplicates
7/19/2012 11:19 AM System Account There was an issue checking duplicates.
7/19/2012 11:19 AM System Account Object reference not set to an instance of an object.
So it seems to be erroring on:
using (SPWeb web = workflowProperties.Web)
To narrow it down, I added a history event right after creating the SPWeb object, and it doesn't hit that. So it's something to do with the top line, which doesn't make sense; the implication is that workflowProperties is uninitialized, but if that were so, it couldn't log the history events, as that's exactly what it's using.
Does anyone have any ideas what I'm doing wrong?