I've written a code to move DocumentSets from one list to another list and I'm talking about a lot of DocumentSets. And this has to happen in every Web and in every Site.
I've written the following code.
foreach (SPSite site in webapp.Sites)
{
try
{
foreach (SPWeb web in site.AllWebs)
{
try
{
SPList library = web.Lists.TryGetList(listName);
foreach(SPListItem item in library.Items)
{
string sourceUrl = "xxx/url/" + item.Title
SPFolder folder = library.ParentWeb.GetFolder(sourceUrl);
if (folder.Exists)
{
SPFieldUserValue userValue = new SPFieldUserValue(list.ParentWeb, item[SPBuiltInFieldId.Author].ToString());
SPUser user = userValue.User;
DocumentSet docSet = DocumentSet.GetDocumentSet(folder);
SPContentTypeId contentTypeId = archiveLibrary.ContentTypes["DocSet"].Id;
byte[] documentSetData = docSet.Export();
string documentSetName = docSet.Item.Name;
SPFolder targetFolder = archiveLibrary.RootFolder;
Hashtable properties = folder.Properties;
DocumentSet.Import(documentSetData, documentSetName, targetFolder, contentTypeId, properties, user);
archivedDocsCounter++;
string fileBatchCmd = string.Format("<SetVar Name=\"owsfileref\">{0}</SetVar>", sourceUrl);
batchStringLibrary.AppendFormat(batchCmd, Convert.ToString(library.ID), folder.Item.ID, fileBatchCmd);
}
}
//process batch to delete items
}
catch (Exception ex)
{
//handle error
}
finally
{
if (web != null)
web.Dispose();
}
}
}
catch (Exception e)
{
//handle error
}
finally
{
if (site != null)
site.Dispose();
}
}
The code is not full but most of it, this happens in a timerjob.
Now in ULS log I see few things which I don't really like:
Closed use of SPRequest, although it is not true as it is still in try catch finally.
Detected use of SPRequest for previously closed SPWeb object. Please close SPWeb objects when you are done with all objects obtained from them, but not before. Stack trace:
at Microsoft.SharePoint.SPFolder.get_Item()
at Microsoft.Office.DocumentManagement.DocumentSets.DocumentSet.Import(Stream archiveStream, String archiveName, SPFolder parentFolder, SPContentTypeId docsetContentTypeId, Hashtable properties, SPUser user)
at Microsoft.Office.DocumentManagement.DocumentSets.DocumentSet.Import(Byte[] archiveBytes, String archiveName, SPFolder parentFolder, SPContentTypeId docsetContentTypeId, Hashtable properties, SPUser user)Potentially excessive number of SPRequest objects
Potentially excessive number of SPRequest objects (17) currently unreleased on thread 12. Ensure that this object or its parent (such as an SPWeb or SPSite) is being properly disposed. This object is holding on to a separate native heap.This object will not be automatically disposed. Allocation Id for this object: {7E96458F-592B-4E45-A535-965DCFB738CA} Stack trace of current allocation:
at Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(SPSite site, String name, Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous)
All this issues come from: DocumentSet.Import any idea if I'm using it wrong somehow? Maybe there is a better way to do that?
UPDATE:
I could establish that the problem comes from this:
DocumentSet.Import(...);
When I comment out this "import" statement, I don't get any messages in the log files. Now the question is how to move document sets correctly?