The technical answer to your original question is a qualified "No": all SPWeb
objects opened from an SPSite
are automatically disposed when the SPSite
is disposed. However, in practice it is a good idea to dispose an SPWeb
as soon as you're done with it to reduce memory pressure, especially when working with code like this that opens several SPWeb
objects.
Implementing this dispose-safe behavior for LINQ is actually quite simple in C#. You can find full details in this post, but the short version is that a C# iterator can handle disposal for you. Using my AsSafeEnumerable()
extension method, your code is relatively safe written like this:
using (SPSite spSite = Utility.GetElevatedSite(_rootUrl))
{
var sw = from SPWeb web in spSite.AllWebs.AsSafeEnumerable()
where web.ServerRelativeUrl.ToLower() == path
from SPWeb subWeb in web.Webs.AsSafeEnumerable()
select subWeb;
foreach(SPWeb aSubWeb in sw)
{
// Do something
}
}
Now the result of your query, which I've assigned to sw
, is a lazy iterator of type IEnumerable<SPWeb>
. As you enumerate over that result, each SPWeb
will be disposed when the enumerator moves to the next item. This means that it is not safe to use that SPWeb
reference, or any SP* object created from it (SPList
, etc), outside of your foreach
loop. Also sw
would not be safe to use outside of that using
block because the iterator's SPWebCollections
will be tied to the now-disposed SPSite
.
That said, code like this that enumerates over all webs (twice!) is extremely expensive. There is almost certainly a more efficient way that this could be implemented, if only by using spSite.AllWebs[path]
instead of your from
/where
.
Regarding garbage collection, these objects require disposal because of unmanaged memory allocated that the GC doesn't even know about.
Finally, a word of caution about your 'GetElevatedSite' utility. If you're using RunWithElevatedPrivileges
in your helper method to get your elevated SPSite
, there are a number of issues you could run into by returning your SPSite
out of that elevated context. If possible, I would suggest using SPSite
impersonation instead - my preferred method is described here.