问题
After reading Stefan Gossner's post about disposing objects and this question about Cross method dispose patterns, I found that I was guilty of accidentally reopening some SPWebs. I know in Stefan Gossner's post he mentions you should dispose of an SPWeb after you are finished with any child object. However, the microsoft documentation mentions Caching the SPListItemCollection object. Is the following code correct? Would the returned SPListItemCollection reopen an SPWeb object? Is there any way to tell for sure?
// is this correct????
private SPListItemCollection GetListItems()
{
SPListItemCollection items = null;
try
{
using (SPSite site = new SPSite(GetListSiteUrl()))
{
using (SPWeb web = site.OpenWeb())
{
// retrieve the list
SPList list = web.Lists[_ListName];
// more code to create the query...
items = list.GetItems(query);
}
}
}
catch (Exception e)
{
// log error
}
return items;
}
Edit 09/09/09
I am mainly referring to this part of Stefan Grossner's post:
You should dispose a SPWeb or SPSite object after the last access to a child object of this object.
I believe what he is saying is that if I use the SPListItemCollection after I dispose of the SPWeb that I used to get it... the SPWeb will be reopened automatically.
回答1:
I found out after asking Stefan directly that the SPListItemCollection can indeed reopen the SPWeb after you dispose of it. This means that my code posted above is INCORRECT and I would only be able to dispose of the SPWeb after I use the SPListItemCollection.
Update: It is better to convert to the SPListItemCollection to something else and return that instead.
private DataTable GetListItems()
{
DataTable table = null;
try
{
SPListItemCollection items = null;
using (SPSite site = new SPSite(GetListSiteUrl()))
{
using (SPWeb web = site.OpenWeb())
{
// retrieve the list
SPList list = web.Lists[_ListName];
// more code to create the query...
items = list.GetItems(query);
// convert to a regular DataTable
table = items.GetDataTable();
}
}
}
catch (Exception e)
{
// log error
}
return table;
}
回答2:
As far as I know the answer is no, but I would have written the code something like
private void FetchItems(Action<SPListItemCollection> action)
{
using(...)
{
var items = list.GetItems(query);
action(items);
}
}
By doing this, to call this method you would need to send a method along (delegate) that the SPListItemCollection should be used for, an example:
FetchItems( items => ....) or FetchItems( DoStuffWithItems(SPListItemCollection) )
回答3:
If you are talking about whether you need an SPWeb in the same scope when you get around to using the SPListItemCollection, I think the answer is no.
For example, I routinely do the following:
private IEnumerable<SPListItem> AllItems;
public void GetItems()
{
var results = SPContext.Current.Web.Lists[ListName].Items.Cast<SPListItem>();
this.AllItems = results;
}
and then I use AllItems all over the place, and it works fine.
Incase you are wondering, the cast is done so I can use Linq on the result set - much much faster than submitting a query to the list, especially if you are doing multiple subselects on the data.
来源:https://stackoverflow.com/questions/1394952/will-using-a-splistitemcollection-returned-from-a-function-reopen-the-spweb