SharePoint

Język CAML jako język zapytań do list SharePoint

Marzec 31, 2016 0
Podziel się:

Jednym z fundamentów platformy SharePoint są listy. Listy to obiekty, w których przechowywane są różnego rodzaju dane. Można je w bardzo dużym uproszczeniu porównać do tabel w bazie danych. Listy tak jak tabele mają swoją strukturę i mogą się między sobą różnić rodzajem przechowywanych danych. Listy mają swoje kolumny oraz typy zawartości (przy czym kolumny i typy zawartości można zdefiniować również na wyższym poziomie w celu ich ponownego użycia). Nieodłączną częścią programowania na platformie SharePoint jest pobieranie danych z list. W niniejszym artykule postaram się w skrócie przedstawić język zapytań używany w SharePoint oraz biblioteki usprawniające pracę z nim.

CAML
W związku z tym, że bezpośrednie odpytywanie bazy SharePoint nie jest zalecanym i dopuszczalnym przez Microsoft sposobem pracy z platformą, język SQL nie jest wykorzystywany do pracy z listami SharePoint. Na potrzeby platformy powstał dedykowany język CAML. CAML (Collaborative Application Markup Language) to język oparty na XML, przy czym wykorzystywany jest nie tylko do odpytywania list, ale też w wielu innych miejscach (np. przy definicji różnego rodzaju artefaktów SharePoint). Możemy z niego korzystać w każdym API SharePoint – Server Side Object Model, Client Side Object Model, JavaScript Object Model i REST API. Przykładowe zapytanie może wyglądać tak:

<Query>
    <Where>
        <And>
            <Eq>
                <FieldRef Name="LastName" />
                <Value Type="Text">Kowalski</Value>
            </Eq>
            <In>
                <FieldRef Name="FirstName" />
                <Values>
                    <Value Type="Text">Jan</Value>
                    <Value Type="Text">Andrzej</Value>
                    <Value Type="Text">Maciej</Value>
                </Values>
            </In>
        </And>
    </Where>
    <OrderBy>
        <FieldRef Name="Modified" Ascending="FALSE" />
    </OrderBy>
</Query>

Jak widać składnia zapytania CAML jest całkiem prosta, natomiast jej zwięzłość pozostawia trochę do życzenia. Gdybyśmy zechcieli na przykład dodać kolejny warunek AND, to nie moglibyśmy dodać kolejnego warunku do istniejącego elementu AND, tylko musielibyśmy tworzyć kolejny i zagnieździć jeden w drugim, ponieważ AND czy OR są tutaj wprost traktowane jak operatory dwuargumentowe. Samodzielne pisanie takich zapytań i sklejanie ich w kodzie na dłuższą metę może być męczące, nawet przy wykorzystaniu narzędzi takich jak U2U CAML Query Builder czy podobnych. Przyjrzyjmy się zatem innym rozwiązaniom.

Camlex.NET
Camlex.NET to biblioteka open source napisana w .NET, która powstała by ułatwić tworzenie zapytań CAML. Pozwala na wykorzystanie drzew wyrażeń w sposób analogiczny jak w LINQ w celu dynamicznego budowania zapytań CAML. Można więc powiedzieć, że pozwala ona na translację drzew wyrażeń do CAML. Biblioteka ta wspiera prawie wszystkie funkcje CAML i jest na tyle dojrzała, że można jej spokojnie używać na środowiskach produkcyjnych. Powyższe zapytanie CAML można by sformułować z wykorzystaniem tej biblioteki w następujący sposób:

string[] firstNames = {"Jan", "Andrzej", "Maciej"};
string caml = Camlex.Query()
	.Where(x =>
		(string)x["LastName"] == "Kowalski" &&
		firstNames.Contains((string)x["FirstName"]))
	.OrderByDescending(x => x["Modified"])
	.ToString();

Z pewnością ten sposób pisania zapytań jest prostszy i bardziej naturalny dla programistów C#. Z oczywistych względów nie wykorzystamy tej biblioteki z poziomu kodu JavaScript – w tym obszarze na ratunek przychodzi inna biblioteka.

CamlJs
CamlJs to biblioteka open source napisana w TypeScript, którą możemy wykorzystać z poziomu kodu TypeScript/JavaScript w sposób bardzo podobny do tego z biblioteki Camlex.NET. Tak jak poprzednio biblioteka ta wspiera większość funkcji CAML i spokojnie można jej używać w kodzie produkcyjnym. Powyższe zapytanie moglibyśmy zbudować za pomocą tej biblioteki w sposób następujący:

var caml = new CamlBuilder()
	.Where()
	.TextField("LastName").EqualTo("Kowalski")
	.And()
	.TextField("FirstName").In(["Jan", "Andrzej", "Maciej"])
	.OrderByDesc("Modified")
	.ToString();

Jak widać tworzenie zapytań w ten sposób jest równie przyjazne jak w przypadku biblioteki Camlex.NET. Warto w związku z tym rozważyć jej użycie, jeśli programujemy w TypeScript/JavaScript.

Wywołanie zapytań CAML
Gdy mamy już zbudowane zapytanie, musimy je jakoś wywołać na odpowiedniej liście. Oto przykłady jak możemy to zrobić z wykorzystaniem różnych API SharePointa (nie są to jednak jedyne sposoby):

SSOM (Server Side Object Model)

using (SPSite site = new SPSite(siteUrl))
using (SPWeb web = site.OpenWeb())
{
	SPList list = web.GetList(listUrl);
	SPQuery query = new SPQuery { Query = caml };
	SPListItemCollection items = list.GetItems(query);
	// Do something with items
}

CSOM (Client Side Object Model)

using (ClientContext context = new ClientContext(siteUrl))
{
	List list = clientContext.Web.Lists.GetByTitle(listTitle);
	CamlQuery camlQuery = new CamlQuery { ViewXml = caml };
	ListItemCollection items = list.GetItems(camlQuery);
	clientContext.Load(items);
	clientContext.ExecuteQuery();
	// Do something with items
}

JSOM (JavaScript Object Model)

function getItems(siteUrl, listTitle, caml) {
    var clientContext = new SP.ClientContext(siteUrl);
    var list = clientContext.get_web().get_lists().getByTitle(listTitle);
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml(caml);
    this.items = list.getItems(camlQuery);
    clientContext.load(this.items);
    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));        
}

function onQuerySucceeded(sender, args) {
	// Do something with this.items
}

function onQueryFailed(sender, args) {
	// On query error
}

REST API (z wykorzystaniem jQuery)

$.ajax({
	url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/getbytitle('listTitle')/GetItems",
	type: "POST",
	headers: {
		"Accept": "application/json;odata=verbose",
		"Content-Type": "application/json;odata=verbose",
		"X-RequestDigest": $("#__REQUESTDIGEST").val()
	},
	data: JSON.stringify({
		query : {
		__metadata: {
			type: "SP.CamlQuery"
		},
		ViewXml: caml
		}
	}),
	success: function (data) {
		// On success
	},
	error: function (error) {
		// On Error
	}
});

Podsumowanie
Niniejszy artykuł z pewnością nie wyczerpuje tego dość złożonego tematu. Warto zapoznać się z dokumentacją języka CAML na MSDN oraz opisanych wyżej bibliotek. Warto również wiedzieć, że zapytania CAML to nie jedyny sposób w jaki możemy odpytywać listy SharePoint. W SSOM możemy np. jeszcze skorzystać z SPMetal (narzędzie stworzone przez Microsoft), za pomocą którego możemy wygenerować kod encji z istniejących list i korzystać z nich podobnie jak z Entity Framework. W REST API możemy z kolei użyć jeszcze OData. Postaram się przybliżyć te tematy w przyszłości.

Dodatkowe informacje
MSDN – Query Schema
Camlex.NET
CamlJs

Oceń ten post
Kategorie: SharePoint
Paweł Hawrylak
Autor: Paweł Hawrylak
Programista .NET z kilkuletnim doświadczeniem. Od dwóch lat związany z technologią Microsoft SharePoint w firmie Sii.

Imię i nazwisko (wymagane)

Adres email (wymagane)

Temat

Treść wiadomości

Zostaw komentarz