Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

this code run yesterday very well and today I've been trying to solve this error for hour now :

Please close SPWeb objects when you are done with all objects obtained from them, but not before

I tried to close each opened web by it still doesn't work !! here's my code I hope someone can help me !

protected void loadItemsFromCorrList(string contentTypeName)
{
    using (SPSite mySite = new SPSite(SPContext.Current.Web.Site.Url))
    {
        // set a data table to fill GridView control with Types Items

        SPListItemCollection collListItems = getAllCorrListItemsforCT(contentTypeName);
        DataTable GVdataSource = new DataTable();
        GVdataSource.Columns.Add(Fields.CorrListFldTypesIN, typeof(string));
        GVdataSource.Columns.Add(Fields.CorrListFldValeurIN);
        GVdataSource.Columns.Add(Fields.CorrListFldOrdreIN);

        foreach (SPListItem myListItem in collListItems)
        {
            DataRow myTypeValueOrderRow = GVdataSource.NewRow();
            myTypeValueOrderRow[Fields.CorrListFldTypesIN] = myListItem[Fields.CorrListFldTypesIN].ToString();
            myTypeValueOrderRow[Fields.CorrListFldValeurIN] = myListItem[Fields.CorrListFldValeurIN];
            myTypeValueOrderRow[Fields.CorrListFldOrdreIN] = myListItem[Fields.CorrListFldOrdreIN];
            GVdataSource.Rows.Add(myTypeValueOrderRow);
        }
        TypeValueOrderGV.DataSource = GVdataSource;
        TypeValueOrderGV.DataBind();
    }
}

protected SPListItemCollection getAllCorrListItemsforCT(string myCTName)
{
   SPList corrList = getSelectedList(Fields.CorrListName);
  using (SPSite mySite = new SPSite(SPContext.Current.Web.Site.Url))
  {
    SPListItemCollection rLIC = null;
    using (SPWeb myWeb = mySite.OpenWeb())
    {
        if (corrList != null)
        {
            SPQuery myQuery = new SPQuery();
            myQuery.Query = "<Where><AND><Eq><FieldRef Name='" + Fields.CorrListFldTitreIN + "'/>"
                + "<Value Type='Text'>" + myCTName + "</Value></Eq>"
                + "<Eq><FieldRef Name='" + Fields.CorrListFldFonctionIN + "'/>"
                + "<Value Type='Text'>" + Fields.GenerateChronoFnTitre + "</Value></Eq></AND></Where>";


            SPListItemCollection allCorrListItems = corrList.GetItems(myQuery);
            Label_Hello.Text += "Hi | " + allCorrListItems[1].Fields[1].ToString();
            rLIC = allCorrListItems;
        }
    }
    return rLIC;
    }
}

getSelectedList(string ListTitle)
{
    using (SPSite mySite = new SPSite(SPContext.Current.Web.Site.Url))
    {
        SPWebCollection myWebs = mySite.AllWebs;
        SPList rList=null;
        foreach (SPWeb myWeb in myWebs)
        {
            using (myWeb)
            {
                SPListCollection myLists = myWeb.Lists;
                foreach (SPList myList in myLists)
                {
                    if (myList.Title.Equals(ListTitle))
                        rList = myList;
                }
            }
            myWeb.Dispose();
        }
        return rList;
    }
}
share|improve this question

4 Answers 4

As Hugh said, in the getSelectedList function you have the first error.

using (myWeb)
{
    SPListCollection myLists = myWeb.Lists;
    foreach (SPList myList in myLists)
    {
        if (myList.Title.Equals(ListTitle))
            rList = myList;
    }
}
myWeb.Dispose();

This will dispose the myWeb istance after the using block. The suggested way from the dispose pattern is instead:

foreach (SPWeb innerWeb in siteCollection.AllWebs)
{
    try
    {
        // ...
    }
    finally
    {
        if(innerWeb != null)
           innerWeb.Dispose();
    }
}

That said, that's not the only problem. You are experiencing an error on "SPListItemCollection allCorrListItems = corrList.GetItems(myQuery);". If you think about it this is expected. You are using the list istance returned by the getSelectedList method, but by now the parent SPWeb istance has already been disposed. You would need to rewrite the code and dispose the web only when you are done working with the list.

Furthermore, the getAllCorrListItemsforCT method seems to open some new SPSite and SPWeb instance that aren't used. Also, the istance are based on the site url, so probably you could just use the SPContext istances (which are automatically disposed for you).


EDIT: About the solutions. IMHO, when you return an SPList istance to a caller method, you are actually delegating the caller to perform appropiate disposing. That said, I would rework the methods to have it so that you pass the web istance to the list finder method - that way you can dispose the istance in the caller method.

share|improve this answer
    
so what should i do ? write it all in the same place ? but what if I needed this fonction again am I gonna write again!! –  Glolita Nov 5 '12 at 14:49
    
Sorry, wrong comment (two windows open at the same time). Give me some time to think about it. –  SPArchaeologist Nov 5 '12 at 16:21

When you create something in a using statement, it gets disposed afterwards.

using(myWeb) {...}
myWeb.Dispose();

You should take off the using statement, and also check to see if the myWeb is disposable.

using (SPWeb myWeb = mySite.OpenWeb())

This instance of use is correct and will auto dispose myWeb.

share|improve this answer
    
it still doesn't work and when I followed the error it's on SPListItemCollection allCorrListItems = corrList.GetItems(myQuery); what does that mean !! –  Glolita Nov 5 '12 at 10:59
1  
You aren't even using mysite and myweb in the second code sample. Also you can just open a list up by it's name: SPList myList = SPWeb.Lists["listname"] without having to iterate through them all. –  Hugh Wood Nov 5 '12 at 11:45
    
@HughWood I would suggest SPWeb.Lists.TryGetList("listname") to avoid handling errors if the list doesn't exist –  tarjeieo Jan 31 '13 at 10:00
    
Yes I should of wrote that but I was using the key which is faster in a project that I know it exists, and automatically wrote that, I wasn't thinking, then you check if(list == null) { code here for the list has been found } –  Hugh Wood Jan 31 '13 at 15:41

Install and run SPDisposeChecker on your compiled dll or exe. It should suggest line items in your code to analyse.

Also, please review Microsoft's excellent article on Best Practices: Using Disposable Windows SharePoint Services Objects

share|improve this answer

The problem with the pattern you've developed to
getSelectedList(string ListTitle) and
protected SPListItemCollection getAllCorrListItemsforCT(string myCTName)
isn't that you forgot to dispose an SPWeb object (of course you should fix the myWeb.Dispose() issue as suggested above).

The problem is that you return SPList and SPListItemCollection from your methods after you've disposed the SPWeb where those objects lie. When you reference to those returned objects somewhere else in your code, SP detects that the web is already disposed and opens it again. If you read carefully the error message "Detected use of SPRequest for previously closed SPWeb object", it suggests that you are referencing to an SPWeb object which has been closed. With this information, you should consider other approach: either not disposing the SPWebs in your methods but only after you're finished handling or making references to the returned SPList and SPListItemCollection or just doing the SPListItemCollection and SPList handling within one using(myWeb) statement.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.