How to query the SPView object

Hugo Migneron picture Hugo Migneron · Jan 11, 2011 · Viewed 8.1k times · Source

I have a SPView object that contains a lot of SPListItem objects (there are many fields in the view).

I am only interested in one of these fields. Let's call it specialField

Given that view and specialField, I want to know if a value is contained in specialField.

Here is a way of doing what I want to do :

String specialField = "Special Field";
String specialValue = "value";
SPList list = SPContext.Current.Site.RootWeb.Lists["My List"];
SPView view = list.Views["My View"]; //This is the view I want to query

SPQuery query = new SPQuery();
query.Query = view.Query;
SPListItemCollection items = list.GetItems(query);
foreach(SPListItem item in items)
{
    var value = item[specialField];
    if(value != null) && (value.ToString() == specialValue)
    {
        //My value is found. This is what I was looking for.
        //break out of the loop or return
    }
}

//My value is not found.

However, iterating through each ListItem hardly seems optimal, especially as there might be hundreds of items. This query will be executed often, so I am looking for an efficient way to do this.

EDIT I will not always be working with the same view, so my solution cannot be hardcoded (it has to be generic enough that the list, view and specialField can be changed.

Would it better to cast it to an IEnumerable object? Say something like this :

list.GetItems(query).Cast<SPListItem>().Where(item => 
{
    return ((item[specialField] != null) && (item[specialField].ToString() == specialValue));
}).Count() > 0;

Would this be more efficient or am I heading in the wrong direction entirely?

Answer

djeeg picture djeeg · Jan 12, 2011
String specialField = "Special Field";
String specialValue = "value";
SPList list = SPContext.Current.Site.RootWeb.Lists["My List"];
SPView view = list.Views["My View"]; //This is the view I want to query

SPQuery query = new SPQuery();
string tmp = view.Query;
if(tmp.Contains("<Where>")) {
    //wrap the existing where clause in your needed clause (it should be an And i think)
    tmp = tmp.Insert(tmp.IndexOf("<Where>") + ("<Where>".Length), "<And><Eq><FieldRef Name='"+specialField+"'/><Value Type='Text'>"+specialValue+"</Value></Eq>");
    tmp = tmp.Insert(tmp.IndexOf("</Where>"), "</And>");
} else {
    //add a where clause if one doesnt exist
    tmp = "<Where><Eq><FieldRef Name='"+specialField+"'/><Value Type='Text'>"+specialValue+"</Value></Eq></Where>" + tmp;
}
query.Query = tmp;
SPListItemCollection items = list.GetItems(query);
if(item.Count > 0) {
    //My value is found. This is what I was looking for.
    //break out of the loop or return
} else {
    //My value is not found.
}