Saturday, April 30, 2011

Using SPSiteDataQuery to find list items by unique ID

In one of my projects I had to search for list item from current site collection by its unique ID that is kept in database as GUID. In this posting I will show you how to query list items by unique ID over current site collection.

Here’s the example query that works fine for me. Take a look at query – unique ID value must be set to type Lookup.


var queryString = @"<Where>

                        <Eq>

                            <FieldRef Name='Unique' />

                            <Value Type='Lookup'>{0}</Value>

                        </Eq>

                    </Where>";           

queryString = string.Format(queryString, taskIdString);

 

var query = new SPSiteDataQuery();

query.Query = queryString;

query.Webs = "<Webs Scope='SiteCollection' />";

query.Lists = "<Lists BaseType='0' />";

query.RowLimit = 1;

query.ViewFields = "<FieldRef Name='Title' />
                    <FieldRef Name='ID' />
                    <FieldRef Name='UniqueId' />"
;


Besides fields defined in ViewFields property the results contain also web and list ID-s where item belongs.

This is the helper method I use to find workflow task with given unique ID. I’m using this code on page where workflow is not present.


public SPListItem GetListItemByUniqueId(Guid uniqueId)

{

    var queryString = @"<Where>
                       <Eq>
                       <FieldRef Name='UniqueId' />
                       <Value Type='Lookup'>{0}</Value>
                       </Eq>
                       </Where>"
;

    queryString = string.Format(queryString, uniqueId);

 

    var query = new SPSiteDataQuery();

    query.Query = queryString;

    query.Webs = "<Webs Scope='SiteCollection' />";

    query.Lists = "<Lists BaseType='0' />";

    query.RowLimit = 1;

    query.ViewFields = @"<FieldRef Name='Title' />
                         <FieldRef Name='ID' />
                         <FieldRef Name='UniqueId' />"
;

 

    var results = SPContext.Current.Web.GetSiteData(query);

    if (results == null)

    {

        return null;

    }

    if (results.Rows.Count == 0)

    {

        return null;

    }

 

    var listId = new Guid(results.Rows[0]["ListId"].ToString());

    var list = SPContext.Current.Web.Lists[listId];

    return list.GetItemByUniqueId(uniqueId);

}


As you can see there’s code enough to keep it in separate method. You can use this method in your own code and you can also modify and improve it to better fit your needs.

1 comment:

  1. Hi,

    There is an issue with that approach when it is updated. Due to list is opened on a current web, but may be on another web. Thus, if item is received only for read purposes - it's ok, but for edit - it crashes.

    ReplyDelete