views:

666

answers:

1

I need help converting the following code snippet to use SPSiteDataQuery instead of SPQuery b/c I need to query accross all Document Libraries in the site.

Here's the original code:

using (SPWeb oWeb = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))
                {
                    SPList oList = oWeb.Lists["Quality Documents"];

                    //create query
                    SPQuery oQuery = new SPQuery();

                    //configure the query  //
                    oQuery.Query = "<Where><Eq><FieldRef Name='Document_x0020_Number' /><Value Type='Text'>" + docNum + "</Value></Eq></Where>";

                    //get the collection of items in the list
                    SPListItemCollection oItems = oList.GetItems(oQuery);

                    if (oItems.Count > 0)
                    {
                        newRnd = 0;
                    }
                    else
                    {
                        newRnd = 1;
                    }
                }

And here's what I have for the SPSiteDataQuery but I don't know if it's correct and/or how to make sure the code does the same thing as the above code.

SPSiteDataQuery q = new SPSiteDataQuery();
q.Lists = "<Lists BaseType='1'/>";
q.Query = "<Where><Eq><FieldRef Name='Document_x0020_Number' /><Value Type='Text'>" + docNum + "</Value></Eq></Where>";
q.Webs = "<Webs Scope='SiteCollection' />";
q.ViewFields = "<FieldRef Name='Document_x0020_Number' />"';
q.RowLimit = 1;
+3  A: 

The main difference between SPQuery and SPSiteDataQuery is in specifying the list to query. Unlike with SPQuery, in SPSiteDataQuery you cannot specify a list title to narrow down your query in each site, you only have the Lists element which is a lot less flexible. Vincent Rothwell describes all of the possibilities here.

This inflexibility means that the use of BaseType=1 in your Lists element code will return documents from all document libraries. The only way you can avoid this is if you deployed a custom list template for Quality Documents with its own ID number. You would then be able to use <Lists ServerTemplate='XYZ' /> (where XYZ is the ID number to narrow results down to that type of list). Otherwise you will need to filter the results you get back so they only contain entries from the Quality Documents library.

Apart from this your code looks equivalent. You may also like to look at CrossListQueryInfo and CrossListQueryCache if you are running MOSS. These allow you to cache SPSiteDataQuery-style queries. See this post by Jeff Dalton for good information on this.

Update from comments about object disposal:

Your code will leak the SPSite object - this needs a using clause as well. Replace the using line you currently have with these lines:

using (SPSite oSite = new SPSite(properties.SiteId))
using (SPWeb oWeb = oSite.OpenWeb(properties.RelativeWebUrl))
{
    // Your code
}

Also, it is easy to use SPDisposeCheck. To integrate with Visual Studio add the following line to your project's post build event:

"%ProgramFiles%\Microsoft\SharePoint Dispose Check\SPDisposeCheck.exe" $(TargetPath)

The build will now fail if you have memory leaks. Check the Output window for details on where they are. Note that SPDisposeCheck sometimes reports false positives and it is possible to ignore these (read the documentation to tell you how).

Alex Angas
Here's what I have come up with...it appears to be working. Does this look to be correct?using (SPWeb oWeb = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl)) {SPSiteDataQuery q = new SPSiteDataQuery();q.Lists = "<Lists BaseType='1'/>";q.Query = "<Where><Eq><FieldRef Name='Document_x0020_Number' /><Value Type='Text'>" + docNum + "</Value></Eq></Where>";q.Webs = "<Webs Scope='SiteCollection' />";q.RowLimit = 1;System.Data.DataTable spSiteDataQueryResults = oWeb.GetSiteData(q);if (spSiteDataQueryResults.Rows.Count > 0){newRnd = 0;}else{newRnd = 1;}}
PushCode
Yes I think so (also see edit). You might also want to run SPDisposeCheck over it, looks like SPSite might be leaking memory.
Alex Angas
Thanks Alex,I'm not familiar with SPDisposeCheck, it looks complex to setup/run. I thought if SPSite and SPWeb were inside 'using' then they are automatically closed and no worries about memory leakage. Is that not the case?
PushCode
Oh, and I am intentially using SPSiteDataQuery for the very purpose of searching the entire document library and not just the Quality Documents library. Just wanted to make sure taht was clear.
PushCode
OK no problem. I've updated the question with details on the memory leak and SPDisposeCheck.
Alex Angas