IT tutorials
 
Technology
 

Sharepoint 2010 : Querying SharePoint Data (part 1) - Querying Using CAML

10/5/2013 4:30:56 AM
- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019

Now that you've been putting a lot of data into your SharePoint server, what are the facilities available to you that allow you to query this data from SharePoint?

There are many ways to pull data out of SharePoint. You can use the object model and get hold of the SPList object, and run a for/each over SPListItems. Of course, that isn't the smartest way to filter for data, though. Filtering via iteration can be extremely resource-expensive.

You could use Search, even programmatically. You can do so by using the FullTextSqlQuery object as demonstrated in an article you can read at http://blah.winsmarts.com/2008-2-SharePoint_Search_ranking_rules_and_running_it_programatically.aspx. While that will provide you with results quickly, it may or may not provide you with accurate results, and certainly has an external dependency on crawl schedules and algorithms. Given the nature of search, you also have limited control over the sorting mechanisms. The sorting is controlled generally by the rank, which is dependent on an algorithm that you can influence, but not fully control. Filtering or querying is more definitive, results are more accurate, and they appear instantaneously. Search requires indexing, may not pinpoint the actual results, but it's less accurate nature, allows the user to execute a search, without knowing exactly what they're looking for. Specifically here we will be talking about querying filtering, not search.

1. Querying Using CAML

CAML, the Collaborative Application Markup Language, is used for many purposes within SharePoint, one of which is extracting the very data you need and striking an excellent balance between speed, dependability, and accuracy.

Within SharePoint, there are a number of objects that make use of CAML and can help you query for data. You would define your CAML query using a syntax as follows:

<Query>
<Where>
<And ...
<BeginsWith ..
<Eq ..
<Contains ..
<Geq ..
... etc.
<Or ...
</Where>
</Query>

You can find a full reference to the CAML syntax at http://msdn.microsoft.com/en-us/library/ms467521.aspx.

Once you do write the CAML query, there are numerous ways to execute this query on your SharePoint server. You can choose to execute this query using the lists web service available at /_vti_bin/lists.asmx. Listing 1 shows an easy way to filter out all rows modified by a given user id, using the lists.asmx web service.

Example 1. Using lists.asmx to Filter Out Rows Modified by a Certain User
XmlDocument camlDocument = new XmlDocument();
camlDocument.LoadXml(
@"<Query>
<Where>
<Or>
<Eq>
<FieldRef Name='Author' />
<Value Type='User'>
Winsmarts\Administrator
</Value>
</Eq>
<Eq>
<FieldRef Name='Editor' />
<Value Type='User'>
Winsmarts\Administrator
</Value>
</Eq>
</Or>
</Where>
</Query>");


using (SP2010.Lists ws = new SP2010.Lists())
{
ws.Credentials =
System.Net.CredentialCache.DefaultCredentials;
ws.Url = "http:// SP2010/_vti_bin/lists.asmx";

XmlNode xView =
camlDocument.CreateNode(
XmlNodeType.Element, "ViewFields", "");
XmlNode xQryOpt =
camlDocument.CreateNode(
XmlNodeType.Element, "QueryOptions", "");

//query the server
XmlNode xNode =
ws.GetListItems(
"Announcements", "",
camlDocument.ChildNodes[0], xView,
"", xQryOpt, "");
}
</div>


Web services have their advantages, but performance and XmlSerialization isn't one of them. So it is reasonable to expect that you have very rich support for CAML in the object model as well. At the heart of it are the SPQuery object and the SPSiteDataQuery object. The SPQuery object and SPSiteDataQuery object are quite similar to each other, except that the SPSiteDataQuery object has the capability to query over an entire site collection. Starting with SharePoint 2010, you can also perform joins between various lists using CAML.

I'll illustrate this with the help of a simple example. You first need to set up some sample data. To set up the sample data, find the "Raw Data.wsp" solution package in your associated code download and then upload and activate it in the solution gallery. Activating the solution will give you a new site definition called "Raw Data". Go ahead and create a subsite at http://sp2010/sampledata based on the "Raw Data" site definition. This newly created site will give you two lists: Artists and Songs. Specifically, the Songs list will have a lookup column pointing to the artist list. This lookup column will allow me to demonstrate the capability of CAML to perform joins between lists.

The sample data for the artist's lists can be seen in Figure 1.

Figure 1. Artists list

And the sample data for the Songs list can be seen in Figure 2.

Figure 2. Songs list

As you can see, I'm pulling in both the Title and the Country column from the artist's list into the Songs list. Next, create a simple SharePoint console application using Visual Studio 2010. I will first demonstrate the ability to query using the SPQuery object without doing a join. What I intend to do is return every song whose artist's name contains a specified input parameter. Because the Artist.title has been pulled into the Songs list, I can perform such a query on the Songs list. Also I will project this data back into a custom business object. Start by adding a class into your console application project, called Song. This class can be seen as –follows:

public class Song
{
public string SongName { get; set; }
public int SongID { get; set; }
public string Country { get; set; }
}

Next, add a method in your console application, as shown in Listing 2.

Example 2. Querying on a Single List Using CAML and SPQuery
public static List<Song> GetSongsByArtist(string artistContainsText)
{
List<Song> songs = new List<Song>();

XmlDocument camlDocument = new XmlDocument();
camlDocument.LoadXml(
@"<Where>
<Contains>
<FieldRef Name='Artist' />
<Value Type='Lookup'>[artistContainsText]</Value>
</Contains>
</Where>".Replace("[artistContainsText]", artistContainsText));

using (SPSite site = new SPSite(siteUrl))
{
SPWeb web = site.OpenWeb();

SPQuery query = new SPQuery();
query.Query = camlDocument.InnerXml;

SPListItemCollection items = web.Lists["Songs"].GetItems(query);

IEnumerable<Song> sortedItems =
from item in items.OfType<SPListItem>()
orderby item.Title
select new Song { SongName = item.Title, SongID = item.ID };

songs.AddRange(sortedItems);
}

return songs;
}


As you can see from Listing 2, I'm executing a CAML query and I'm using a "contains" clause to filter out all items where the Artist column contains the specified input word "artistContainsText". I then execute this query on the Songs list using the GetItems method. Finally I execute a LINQ query to create a projection of this data in my custom business object, which I return from this method.

Thus the usage of this method becomes really simple:

List<Song> songsMichael = GetSongsByArtist("Michael");
foreach (var song in songsMichael)
{
Console.WriteLine(song.SongName);
}

Running this code should show an output as shown in Figure 3.

Figure 3. Results of a Simple CAML Query

As you can see, all the songs are either from Michael Jackson or George Michael. Both of them have the word Michael in their name, so both of their songs are matched.

This is great, but sometimes you do not have the projected fields available in the related lists. In those scenarios, it is very useful to be able to perform joins between these lists. The ability to create joins is a little bit different from joins in an SQL server. Joins in SharePoint are driven off of lookup-based columns. In order to support joins in CAML queries, CAML queries in SharePoint 2010 and their associated objects have been enhanced to support these:

  • <Joins> element in CAML and the SPQuery.Joins property

  • <ProjectedFields> element in CAML and the SPQuery.ProjectedFields property

Next let us look at an example, in which I will query the Songs list for all songs whose title contains an input string. Then I will use joins and create projected fields from the Artist list to show which song comes from which country. You can achieve this by using the code shown in Listing 3.

Example 3. Ability to Create Joins Using the SPQuery object and CAML
public static List<Song> GetSongsByName(string titleContainsText)
{
List<Song> songs = new List<Song>();

XmlDocument camlDocument = new XmlDocument();
camlDocument.LoadXml(
@"<Where>
<Contains>
<FieldRef Name='Title' />
<Value Type='Text'>[titleContainsText]</Value>
</Contains>
</Where>".Replace("[titleContainsText]", titleContainsText));


using (SPSite site = new SPSite(siteUrl))
{
SPWeb web = site.OpenWeb();

SPQuery query = new SPQuery();
query.Query = camlDocument.InnerXml;
query.Joins =
@"
<Join Type='LEFT' ListAlias='Artist'>
<Eq>
<FieldRef Name='Artist' RefType='Id'/>
<FieldRef List='Artist' Name='ID'/>
</Eq>
</Join>
";

query.ProjectedFields =
@"
<Field Name='Country' Type='Lookup' List='Artist' ShowField='Country'/>
";

SPListItemCollection items = web.Lists["Songs"].GetItems(query);

IEnumerable<Song> sortedItems =
from item in items.OfType<SPListItem>()
orderby item.Title
select new Song { SongName = item.Title, SongID = item.ID, Country =
item["Country"].ToString()};

songs.AddRange(sortedItems);
}
return songs;
}


As you can see from Listing 3, I'm embellishing a simple CAML query with a specified join and specified projected fields. Then, as before, I'm executing a LINQ query to create a projection of this data into my custom business object, and I am returning that custom business object from this method. This code can be executed as shown here:

List<Song> songsA = GetSongsByName("A");
foreach (var song in songsA)
{
Console.WriteLine("{0} is from {1}", song.SongName, song.Country);
}

Executing the preceding code should show the output shown in Figure 4.

Figure 4. Results of a CAML join

As you can see, not only are you showing the titles of the songs but you can also perform a join with the artist's lists and show which country the song came from. Nevertheless, there are some things I don't like about this code. For one, it shows that weird ID that looks like 1;#. Then the CAML queries aren't a lot of fun to write, and the errors I make in CAML queries will be caught at runtime, not compile time. Is there a better way?

 
Others
 
- Windows Small Business Server 2011 : Creating a Data Collector Set (part 3) - Scheduling Data Collection
- Windows Small Business Server 2011 : Creating a Data Collector Set (part 2) - Constructing a Data Collector Set Manually
- Windows Small Business Server 2011 : Creating a Data Collector Set (part 1) - Building a Data Collector Set from a Template
- Windows Small Business Server 2011 : Using Reliability Monitor, Managing Collected Data
- Windows 8 : BitLocker Drive Encryption: The Essentials (part 3) - Deploying BitLocker Drive Encryption
- Windows 8 : BitLocker Drive Encryption: The Essentials (part 2) - Hardware Encryption, Secure Boot, and Network Unlock
- Windows 8 : BitLocker Drive Encryption: The Essentials (part 1) - Understanding BitLocker Drive Encryption
- System Center Configuration Manager 2007 : Patch Management - Troubleshooting Software Updates
- System Center Configuration Manager 2007 : Patch Management - Using NAP to Protect Your Network (part 2) - System Health , Client Compliance
- System Center Configuration Manager 2007 : Patch Management - Using NAP to Protect Your Network (part 1) - NAP Prerequisites , Agent Settings
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
Technology FAQ
- Is possible to just to use a wireless router to extend wireless access to wireless access points?
- Ruby - Insert Struct to MySql
- how to find my Symantec pcAnywhere serial number
- About direct X / Open GL issue
- How to determine eclipse version?
- What SAN cert Exchange 2010 for UM, OA?
- How do I populate a SQL Express table from Excel file?
- code for express check out with Paypal.
- Problem with Templated User Control
- ShellExecute SW_HIDE
programming4us programming4us