Wednesday, July 09, 2008

SPSiteDataQuery Vs. CrossListQueryInfo


No body really thought of comparing these two guys.. i heared people always comparing SPSiteDataQuery and PortalSiteMapProvider. Good post by Tone Stegeman:

When I was writing the querying part of the new Content By Type webpart that I will introduce shortly, I noticed there are 2 ways you can use to query SharePoint sites for content. The first is well known and described in a lot of articles on the web. In the method we use the SPSiteDataQuery object to get the data we want. Below you find an example.

    string lists = "<Lists BaseType=\"5\" />";
    string viewFields = "<FieldRef Name=\"Title\" />";
    string webs = "<Webs Scope=\"SiteCollection\" />";
    SPSiteDataQuery siteQuery = new SPSiteDataQuery();
    siteQuery.Lists = lists;
    siteQuery.ViewFields = viewFields;
    siteQuery.Webs = webs;
    results = SPContext.Current.Web.GetSiteData(siteQuery);


This query returns the title of all items in Issue lists in all sites in the current site collection. Nothing special here. This method of crawling for content works in both WSS and in MOSS. If you are running Microsoft Office SharePoint Servers, you can also use the CrossListQueryInfo object to query for content. The advantage is that SharePoint has a caching mechanism for the queries that you run. By
using CrossListQueryInfo, your webpart will use this caching mechanism. And you can also make use of audience targeting. See this link for more info.

The query of the previous example now looks like this:



    string lists = "<Lists BaseType=\"5\" />";
    string viewFields = "<FieldRef Name=\"Title\" /><FieldRef Name=\"ContentType\" />";
    string webs = "<Webs Scope=\"SiteCollection\" />";
    CrossListQueryInfo query = new CrossListQueryInfo();
    query.RowLimit = 100;
    query.WebUrl = SPContext.Current.Site.ServerRelativeUrl;
 
    query.Lists = lists;
    query.Webs = webs;
    query.Query = "<Where><Neq><FieldRef Name=\"ContentType\" /><Value Type=\"Text\"></Value></Neq></Where>";
    query.ViewFields = viewFields;
 
    CrossListQueryCache cache = new CrossListQueryCache(query);
 
    results = cache.GetSiteData(SPContext.Current.Site);


Please not that for this query I added a where statement to the query. This just checks for items that have a value in the ContentType field. If you don't specify a query, the GetSiteData method will generate an error message.

A warning if you are querying your sites using field names instead of IDs. When testing my Content By Type webpart, I started querying using the field names (SPField.InternalName) that I got from the site columns that are attached to the content type. I found that there are a number of issues with this. The internal name of the site columns are not exactly the same as the internal names of the fields that are used in the lists. This is caused by little differences in the site column features and the schema XML files for the lists. the Task content type for example contains a field with internal name "TaskDueDate" The Task lists in your sites however have a field called "DueDate". If you query using TaskDueDate, you will not get the results you expeect. Below you find these exceptions:


  • Task: TaskDueDate in content type is called DueDate in list
  • Task: TaskStatus in content type is called Status in list
  • Issue: IssueStatus in content type is called Status in list
  • Contact: EMail in content type is called Email in list
  • Picture: Comments in content type is called Description in list

So I ended up querying using the ID guid of the fields. This applies to both methods described above.


7 comments:

Anonymous said...

Found the magic decoder for the view field names. The fieldname is OWS name less "ows_".

Yikes!! Several hours figuring this out.

The U2U CAML Buider gives you a good clue to the correct names.

Dave

Adil A. Baig said...

yeah it sure is

U2U guys have done SOME work here!!!

Marius C.tinescu said...

You are right yes, there some pretty nice tools outhere, but have you the SPBuiltInFieldId? (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spbuiltinfieldid_members.aspx).

Still for your own fields (or other custom for that matter) you would need to user other tricks!

Regards,
C. Marius(c_marius@msn.com)

Anonymous said...

you seem to have exact same text as this article : http://www.tonstegeman.com/Blog/Lists/Posts/Post.aspx?ID=47

Adil A. Baig said...

yes offcourse, better to spread the word then keep it with you.

Karine Bosch said...

Hi Adil,
I just fell on your blog because I was looking for info on CrossListQueryInfo. Thanks for this post.
I also remarked that you have known Patrick Tisseghem, so I wanted to say hello. I'm Karine Bosch, his technical assistant, and developer of the CAML Builder, (so it's in fact a girl that has done some good work :) )
Keep on blogging!
Karine

digital signature PDF said...

Excellent! Thanks for this - I've been looking at this feature for ages. Followed your instructions and it works a treat!