# DocumentSet.Import and Detected use of SPRequest for previously closed SPWeb object

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?

## 1 Answer

Properly dispose the spweb and spsite,

add your logic in the following snippet,

 foreach (SPSite siteColl in webapp.Sites)
{
SPWebCollection collWebsite = siteColl.AllWebs;

for (int i = 0; i < collWebsite.Count; i++)
{
using (SPWeb oWebsite = collWebsite[i])
{
//add your logic here
}
}

siteColl.Close();
}


for more details refer this

• I don't see the difference, I have site.Dispose() and web.Dispose() in finally block, why is this different then what you are proposing and how can this help? – Shkipper May 22 '17 at 7:45
• As per your stack trace posted here it is clear that issue is related to incorrect disposal of web objects.so by using the snippet here, it can correct the order of disposing. – SynozeN Technologies May 22 '17 at 7:48
• so basically the thing I do is instead of using foreach i'll be using for ... right? and this should solve the issue? – Shkipper May 22 '17 at 7:52
• No, instead of using web.Dispose(); dispose it by using (SPWeb oWebsite = web){}.keep your foreach as it is n just wrap your code inside using statements. – SynozeN Technologies May 22 '17 at 8:09
• I still don't understand what is the difference, sorry ... your URL says here: foreach (SPWeb web in site.AllWebs) { // do something with the web object web.dispose(); // <– this is mandatory! } – Shkipper May 22 '17 at 8:18