SharePoint Blogs / SharePoint University
SharePoint Blogs and SharePoint University - all in one place!
Need SharePoint Training? Attend a SharePoint Bootcamp!

Please delete cookies related to sharepointblogs.com and sharepointu.com to resolve login issues!

Implementing SPSiteDataQuery - Learning by doing

(Migrated post from June 19th, 2007; Updated on July 12th (see comments))

Facing the challenge to write a custom query that spans multiple lists that contain subfolders and a rather complex set of metadata, we had to evaluate both methods of querying lists:

  • SPQuery
  • SPSiteDataQuery

Looking at the SPQuery, the implementation is a piece of cake. However, there is a known limitation that SPQuery will return only results of one folder, you’ll never get search results from any of the subfolders contained in the library:

(from the WSS 3.0 SDK):
SPQuery can only get the items in the current folder; SPQuery will not get the items in subfolders. This is the design feature in SharePoint Portal Server 2003. To get the items in subfolders, it is necessary to change to the subfolder in SPQuery first. Also it is necessary to specify the format for using dates in the query.

OK, this is what I also knew SharePoint Portal Server 2003... But hey, aren't we in the WSS 3.0 SDK???  And thanks to the tip of  "Nick" (see comments) I know know that it is absolutely possible to query also subfolders with the SPQuery:  msdn2.microsoft.com/.../microsoft.sharepoint.spquery.viewattributes.aspx

query.ViewAttributes = "Scope=\"Recursive\"";

OK, so far so good. But let’s look now at SPSiteDataQuery which is new in WSS 3.0 – and you’ll notice!

First of all, make sure that you really read and understand (and least try!) the documentation at http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.spsitedataquery.aspx.

Only if you stay 100% within the given specification, you’ll be able to obtain results, otherwise, you’ll always get zero search results.

Here are some of my findings:

  • You must write the CAML query without the “<Query>” Element.
  • If writing the CAML Query as a string, you must not use any line breaks or additional whitespaces.
    • Example of a working query:
      "<Where><Eq><FieldRef Name='TestLookupMulti' /><Value Type='Text'>abc</Value></Eq></Where><OrderBy><FieldRef Ascending='False' Name='Title' /></OrderBy>"
    • Example of an “invalid” query (sorry, I've seen the comment, but this one did not work for me!):
      @“<Where>
                             <Contains>
                                                     <FieldRef Name='TestLookupMulti' />
                                                     <Value Type='MultiLookup'>SubFolder</Value>
                             </Contains>
       </Where>
      <OrderBy>
                             <FieldRef Ascending='False' Name='Title' />
      </OrderBy>"


  • In order to query for individual metadata fields (fields that not present in every list like “Title” or “ID”) you must include the “Nullable=’true’” Attribute in the <fieldref>-Element of the ViewFields. However: This does not work for lookups and person-fields! If you are using custom lookups, you must restrict the lists that are searched using the <Lists> Element. Here is a working example:
    spDataQuery.Lists = "<Lists><List ID='" + myTestListID + "' /></Lists>";
  • You may use Lookup and even Multivalue-Lookups for your queries. Even the <Eq> Operator works on Multivalue-Lookups! However, up to my knowledge, it is not possible to show a Multivalue-Lookup in the ViewFields! Every attempt to do this will result in zero search results!

I will now provide a working example that uses bot: SPQuery and SPSiteDataQuery.
Create a PictureLibrary called “MyPictures” with some subfolders. Add the following metadata:

  • “Test” à Simple Text
  • “TestLookupSingle” à Single-Select Lookup
  • “TestLookupMulti” à Multi-Select Lookup

Use the code below in a test windows application (running on the server!) and make sure you have the necessary privileges to execute the query on MOSS:

            string myTestCAMLQuery = "<Where><Contains><FieldRef Name='TestLookupMulti' /><Value Type='Text'>TestValue</Value></Contains></Where><OrderBy><FieldRef Ascending='False' Name='Title' /></OrderBy>";

            // Get test variables

            SPWeb myTestWeb = new SPSite("http://mho-dev07:8080/").OpenWeb(); // Add your site url/web url here

            SPList myTestList = myTestWeb.Lists["MyPictures"];

            string myTestListID = myTestList.ID.ToString();

           

            // Test 1: use SPQuery

            SPQuery spQuery = new SPQuery();

            spQuery.Query = myTestCAMLQuery;

            SPListItemCollection spQueryResults = myTestList.GetItems(spQuery);

            Debug.WriteLine(spQueryResults.Count);

            // Test 2: use SPSiteDataQuery

            SPSiteDataQuery spDataQuery = new SPSiteDataQuery();

            spDataQuery.Query = myTestCAMLQuery;

            spDataQuery.Webs = "<Webs Scope='SiteCollection' />"; // could also use "Recursive"

           

            // Most important: Must restrict to the target lists containing the fields

            // see http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.spsitedataquery.viewfields.aspx

            // for details.

            spDataQuery.Lists = "<Lists><List ID='" + myTestListID + "' /></Lists>";

            // Make sure to include all fields wanted in ViewFields

            spDataQuery.ViewFields = "<FieldRef Name='TestLookupSingle' />";

            spDataQuery.RowLimit = 100;

            System.Data.DataTable spSiteDataQueryResults = myTestWeb.GetSiteData(spDataQuery);

            Debug.WriteLine(spSiteDataQueryResults.Rows.Count);

 


Posted 06-28-2007 2:16 PM by mhofer1976

Comments

Links (6/28/2007) « Steve Pietrek’s SharePoint Stuff wrote Links (6/28/2007) &laquo; Steve Pietrek&#8217;s SharePoint Stuff
on 06-28-2007 8:42 PM

Pingback from  Links (6/28/2007) &laquo; Steve Pietrek&#8217;s SharePoint Stuff

Oskar Austegard wrote re: Implementing SPSiteDataQuery - Learning by doing
on 07-11-2007 12:54 PM

This is incorrect: "If writing the CAML Query as a string, you must not use any line breaks or additional whitespaces."  You can indeed use the "invalid" (aka human readable) query format with whitespace.

Nick wrote re: Implementing SPSiteDataQuery - Learning by doing
on 07-11-2007 4:48 PM

SPQuery can include subfolders: msdn2.microsoft.com/.../microsoft.sharepoint.spquery.viewattributes.aspx

query.ViewAttributes = "Scope=\"Recursive\"";

Perhaps this was a change from 2003, which is what your quote of the WSS 3 sdk specifies.

mhofer1976 wrote re: Implementing SPSiteDataQuery - Learning by doing
on 07-12-2007 8:37 AM

@Nick: Hey, great tip. I am amazed because we have used the Scope Attributes to set the reach of the SiteDataQuery before, so we did not look at it anymore that closely for the SPQuery. It solves indeed a lot of problems and I will change my posts. Thanks.

Mirrored Blogs wrote Solution: SPQuery Does Not Search Folders
on 02-16-2008 11:12 AM

This past week I was implementing an &quot;evolving&quot; solution for a client that uses BDC and SPQuery

mano wrote re: Implementing SPSiteDataQuery - Learning by doing
on 06-02-2008 7:36 AM

out of topic but ..

if you use the below to get an instance of SPWeb..

SPWeb myTestWeb = new SPSite("http://mho-dev07:8080/").OpenWeb();

you will not get a chance to dispose off the SPSite

on3 wrote re: Implementing SPSiteDataQuery - Learning by doing
on 06-18-2008 6:27 PM

@mano

so what is your suggestion?

Saurabh wrote re: Implementing SPSiteDataQuery - Learning by doing
on 07-10-2008 5:54 AM

Hi Michael

I am trying to use SPSiteDataQuery and put 3 SPLists

In each SPLIst i have a SiteColumn name "ID"

Now how can SPSiteDataQuery know.....the ID m giving in the query is of List1's ID or List2's ID or List3's ID

dQuery.Query = @"<Where> <Gt>

                               <FieldRef Name=""ID""/>

                                               <Value Type=""Counter"">0</Value></Gt></Where>";

How Does it knows.....which List's ID m using in the Query.......?

Rodrigo Zotto wrote re: Implementing SPSiteDataQuery - Learning by doing
on 09-12-2008 8:35 AM

Good Morning!

I need show values stored in field 'ContatoCad', this field is a multiple values lookup, this field not used in filter(where tag), but I need get this values to show in my custom webpart.

My query return 0 rows.

do you can help-me?

string CAMLQuery =

                               @"<Where>" +

                               "<Eq>" +

                               "    <FieldRef Name='ID' />" +

                               "    <Value Type='Text'>{0}</Value>" +

                               " </Eq>" +

                               "</Where>" +

                               "<OrderBy>" +

                               "   <FieldRef Name='Title' />" +

                               "</OrderBy>";

crossListInfo.ViewFields = @"<FieldRef Name='ConfigEixo'/>" +

                                               "<FieldRef Name='MarcaCad'/>" +

                                               "<FieldRef Name='AnoFabCad'/>" +

                                               "<FieldRef Name='AnoModeloCad'/>" +

                                               "<FieldRef Name='CorCad'/>" +

                                               "<FieldRef Name='KmCad'/>" +

                                               "<FieldRef Name='PlacaCad'/>" +

                                               "<FieldRef Name='ChassiCad'/>" +

                                               "<FieldRef Name='ValorVendaCad'/>" +

                                               "<FieldRef Name='LojaCad'/>" +

                                               "<FieldRef Name='Foto1'/>" +

                                               "<FieldRef Name='ObsCad'/>" +

                                               "<FieldRef Name='Foto2'/>" +

                                               "<FieldRef Name='Foto3'/>" +

                                               "<FieldRef Name='Foto4'/>" +

                                               "<FieldRef Name='ContatoCad'/>" +

                                               "<FieldRef Name='ModeloCad'/>";

Suresh Kumar v.c wrote re: Implementing SPSiteDataQuery - Learning by doing
on 06-12-2009 11:17 AM

Hi, am new to sharepoint . I have a list populated with some date values and names. Now I want to add a button on that list to display a report of names between dates taking parameters from user . How should I do this. If I dont know how to implement this spdataquery. I am a developer. Please tell me from scratch from coding to deploying.

Can somebody help me

regards,

suresh kumar vc

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Need SharePoint Training? Attend a SharePoint Bootcamp!
Posts (c) their respective authors. Everything else (c) 2009 SharePoint Experts, Inc.