2

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?

Hugo Migneron
  • 4,867
  • 1
  • 32
  • 52
  • why dont you append a clause in the query. An example http://msdn.microsoft.com/en-us/library/ms457534.aspx – Sandeep Singh Rawat Jan 11 '11 at 21:01
  • Because I don't know what the query will look like (the view query that is). If there is an OrderBy clause for example, I can't just add a where clause after (it would give a ......... and that doesn't work. – Hugo Migneron Jan 11 '11 at 21:28
  • 1
    The Where clause would look like ... FIELD COMPARES FIELD + ORDER , CAML works just like XML, even though it looks like multiple rootnodes, only the entire thing sent to SPQuery is encapsulated in a tag by the SPView object , just look for SharePoint CAML on Google – Colin Jan 11 '11 at 22:53
  • 1
    You're heading in the wrong direction! ;) The root of the problem is retrieving a large recordset with mostly irrelevant records and then looping through them. Even casting to IEnumarable and doing .Where() is still doing that under the hood. Use the feature given by SharePoint - figure out how to add the WHERE into CAML so its valid even if you've got order by etc. – Ryan Jan 12 '11 at 10:37

2 Answers2

3
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.
}
djeeg
  • 6,685
  • 3
  • 25
  • 28
  • Haven't tested but looks good so +1 from me. An alternative would be to put the CAML into a XmlDocument and parse/modify via the DOM. – Ryan Jan 12 '11 at 10:38
  • Yeah, this looks like it's the way to go as I would only have to query once. Let me get this working and i'll mark as accepted. Thanks for your help! – Hugo Migneron Jan 12 '11 at 14:43
  • This works very well. Just a note though : inside the first if, the first line should start with tmp = tmp.Insert(tmp.IndexOf("") + ("".Length)... (I removed the +1) for it to work properly. Thanks again! – Hugo Migneron Jan 12 '11 at 19:07
0

You can execute queries in Caml. This is a good link for understanding queries in Caml and this is a link to software for building queries automatically.

Chris Frederick
  • 5,482
  • 3
  • 36
  • 44
Michaël
  • 6,676
  • 3
  • 36
  • 55
  • I'm already doing a CAML query to get the SPListItems from the view... Is there a way to do a CAML query directly on the SPView object? If I have to use CAML to first get the SPListItems from the list, then use CAML again to query that set i'm not sure it will be so efficient. Do you have an exemple, keeping in mind that I am working with a view as a base set, not a list. – Hugo Migneron Jan 11 '11 at 20:07