(一)概述web
在SharePoint的開發應用中,查詢是很是經常使用的一種手段,根據某些篩選、排序條件,得到某個列表或者某一些列表中相應的列表條目的集合。數據庫
除去列表上的查詢以外,在SharePoint中還大量存在着各類各樣的查詢,好比針對回收站的SPRecycleBinQuery、針對審計的SPAuditQuery、針對變動的SPChangeQuery等等,不過這些查詢在實際項目中使用到的頻率並非很高。本章節仍是着重介紹列表查詢功能。app
在SharePoint 2010以前,列表查詢的查詢語句都是經過CAML這樣一種XML格式來編寫的。對於開發人員來說,準確快速地編寫出較爲複雜的CAML查詢並不是是一件垂手可得的事情,可是使用CAML進行數據查詢還是SharePoint開發中不可或缺的技能。本節將介紹如何使用CAML進行列表查詢和跨多個列表之間的查詢,在下一節中將介紹SharePoint 2010新引入的列表查詢方式——LINQ。性能
(二)CAML查詢字符串網站
在列表查詢中,全部的查詢條件都要使用一種Xml形式的語法進行描述,這種Xml語法被稱做CAML(Collaborative Application Markup Language),是SharePoint中一種特定的Xml語法。實際上,在SharePoint中不只是列表查詢使用了CAML,在網站、列表、字段、內容類型、網站功能等各類對象的定義中,也大量使用了CAML格式的Xml。spa
CAML查詢字符串總的來講能夠分爲3大部分:篩選條件、排序和分組條件、返回字段。code
在編寫CAML字符串的時候,須要特別注意Xml標籤的大小寫是敏感的。對象
一、篩選條件排序
使用CAML格式的篩選條件能夠理解爲是將傳統的數據庫中的SELECT語句以Xml的形式進行標準化,便於計算機的解析和閱讀。事件
CAML格式的篩選條件使用<Where></Where>做爲最外層結點,標誌篩選條件的範圍。篩選條件能夠由若干個子篩選條件組成,每一個子篩選條件的格式都相似於:
<操做符><字段/><值/></操做符> 至關於: [字段] [操做符] [值]
其中操做符部分通常應用中包括:Eq(等於)、Neq(不等於)、Lt(小於)、Leq(小於等於)、Gt(大於)、Geq(大於等於)、Contains(包含)、BeginsWith(以某字符串開頭)、In(在集合範圍內)、IsNull(爲空)、IsNotNull(不爲空)、Membership(屬於用戶組)。最後三個操做符是一元操做符,沒有其中的「值」的部分。
字段部分的格式爲:<FieldRef Name="字段名" 其餘屬性 />,特別注意不要遺忘最後的「/」終結符,字段名必須使用內部名稱。
值部分的格式爲:<Value Type="類型">值</Value>,其中類型部分根據不一樣的字段有不一樣的設置,經常使用的包括Text(文本)、Number(數值)、DateTime(日期)、Lookup(查閱項)等等。
例如,咱們要在列表中查詢「標題」字段(內部名稱爲Title)包含字符串「對象模型」的那些列表條目,若是是傳統的T-SQL語句寫法,應該是形如:
1: SELECT * FROM xxList WHERE 標題 Contains '對象模型'
可是在SharePoint中,使用CAML格式描述後,就變成了:
1: <Where>
2: <Contains>
3: <FieldRef Name='Title' />
4: <Value Type='Text'>對象模型</Value>
5: </Contains>
6: </Where>
從查詢條件的格式中能夠看出,SharePoint在進行列表查詢的時候,只支持字段與值的比較,而不支持兩個字段之間的比較,這是一個較大的限制。
二、一些特殊的篩選條件
這裏列出一些比較特殊的篩選條件的寫法(均省略其中的Where標籤):
(1)包含在集合範圍內的查詢,這是SharePoint 2010新增長的一種查詢類型,使用「In」操做符來查詢包含在指定範圍內的集合。例以下面的例子查找了Writer包含在[「Erucy」, 「Windie」]集合的章節(即Writer等於Erucy或Windie的章節):
1: <In>
2: <FieldRef Name='Writer'/>
3: <Values>
4: <Value Type='Text'>Erucy</Value>
5: <Value Type='Text'>Windie</Value>
6: </Values>
7: </In>
(2)「是/否」類型的查詢,該類型在數據庫中其實是bool類型,在查詢的時候使用「1」表示「是」,使用「0」表示「否」,例如:
1: <Eq>
2: <FieldRef Name='BoolField'/>
3: <Value Type='Boolean'>1</Value>
4: </Eq>
(3)某我的員和組類型的字段等於當前用戶,若是是多選的話其中包含當前用戶:
1: <Eq>
2: <FieldRef Name='UserField'/>
3: <Value Type='Integer'><UserID/></Value>
4: </Eq>
(4)若是某個「用戶或用戶組」類型的字段填寫的是用戶組,篩選用戶組包含當前用戶的:
1: <Membership Type='CurrentUserGroups'>
2: <FieldRef Name='UserField'/>
3: </Membership>
(5)默認狀況下,對於時間和日期類型的查詢只精確到日期,若是須要精確到時間:
1: <Gt>
2: <FieldRef Name='DateTimeField' />
3: <Value Type='DateTime' IncludeTimeValue='TRUE'>
4: 2009-10-08T17:48:37Z
5: </Value>
6: </Gt>
(其中的日期格式能夠經過使用一個靜態方法SPUtility.CreateISO8601DateTimeFromSystemDateTime轉換獲得)
(6)通常狀況下,進行查閱項或用戶篩選的時候,可使用Text類型的Value,判斷查閱的列表條目的文本或用戶的現實名稱的字符串;若是須要精確按照被查閱條目的ID或用戶的ID進行查找的話(對於多選查閱項和多選用戶也應使用Eq操做符,而不是Contains操做符):
1: <Eq>
2: <FieldRef Name='LookupField' LookupId='TRUE'/>
3: <Value Type='Lookup'>37</Value>
4: </Eq>
(7)在日曆模板類型的列表中,當須要查詢某個指定時間範圍內的事件的時候,若是是經過Gt/Geq和Lt/Leq方式查找,僅能查找到非重複事件,以及重複事件的第一次事件,爲了可以準確地查找某個範圍內的重複事件,須要使用DateRangesOverlap查詢操做符,並配合SPQuery的一些屬性進行。(在跨列表查詢中不支持重複事件)
1: <DateRangesOverlap>
2: <FieldRef Name='EventDate' />
3: <FieldRef Name='EndDate' />
4: <FieldRef Name='RecurrenceID' />
5: <Value Type='DateTime'>
6: <Today />
7: </Value>
8: </DateRangesOverlap>
DateRangesOverlap操做符的寫法相對比較固定,其中的EventDate是「開始時間」的內部名稱;EndDate是「結束時間」的內部名稱;RecurrenceID是某個和重複事件相關字段的內部名稱。Value中的標籤訂義了查詢的範圍,包含以下4種:<Today/>(天)、<Week/>(周)、<Month/>(月)、<Year/>(年)。
查詢的時候須要配合使用SPQuery的兩個屬性:ExpandRecurrence(bool類型)須要設置爲true,表示查詢的時候展開重複事件(即便沒有重複事件,在使用操做符DateRangesOverlap的時候也應當設置此屬性);CalendarDate(DateTime類型),設置查詢範圍的日期。例如,下面的程序查詢了明天的全部事件(咱們能夠先提早了解一下SPQuery的使用):
1: using(SPSite site = new SPSite("http://sp2010/book"))
2: {
3: using(SPWeb web = site.OpenWeb())
4: {
5: SPList calList = web.Lists["日曆"];
6: SPQuery query = new SPQuery();
7: query.ExpandRecurrence = true;
8: query.CalendarDate = DateTime.Today.AddDays(1);
9: query.Query = "<DateRangesOverlap>" +
10: "<FieldRef Name='EventDate' />" +
11: "<FieldRef Name='EndDate' />" +
12: "<FieldRef Name='RecurrenceID' />" +
13: "<Value Type='DateTime'><Today /></Value>" +
14: "</DateRangesOverlap>";
15: SPListItemCollection tomorrowEvents = list.GetItems(query);
16: foreach(SPListItem event in tomorrowEvents)
17: Console.WriteLine(event.Title);
18: }
19: }
對於其餘類型的查詢條件,能夠參考SDK中的相關章節(在英文版的SDK中,CAML查詢參考的位置在:SharePoint Foundation 2010 General Reference – Services References – SharePoint Schema References – CAML Core Schemas – Query Schema)。
三、篩選條件中的邏輯運算
在CAML中也支持多個查詢條件的邏輯組合,支持「與」和「或」,可是不支持「非」。經過<And></And>和<Or></Or>標籤(注意大小寫)進行邏輯運算。
不過須要特別聲明的是,And標籤和Or標籤內部,只能使用兩個查詢條件。例如以下的查詢條件是非法的(Cond表示每一個子查詢條件):
1: <Where>
2: <And>
3: <Cond1/><Cond2/><Cond3/>
4: </And>
5: </Where>
應當寫成:
1: <Where>
2: <And>
3: <And>
4: <Cond1/><Cond2/>
5: </And>
6: <Cond3/>
7: </And>
8: </Where>
經過這種方式來保證每一個邏輯運算標籤內,有且僅有兩個子條件。
固然,And標籤和Or標籤能夠進行交替使用,組成複雜的邏輯篩選條件。
四、排序條件
在CAML查詢中,使用<OrderBy></OrderBy>指定0至多組排序條件。
查詢條件中每一個字段按照排列的順序依次爲首要查詢條件、次要查詢條件、第三查詢條件等等,其中每一個查詢條件的寫法爲:
1: <FieldRef Name='字段名' Ascending='TRUE|FALSE' />
其中的Name屬性一樣必須使用內部名稱,Ascending屬性指定是不是正向排序(從小到大),若是不包含該屬性,則默認爲正向排序。
例如,下面的CAML片斷指定了查詢的排序條件爲先按照做者(內部名稱爲Author)再按照建立時間由新到舊(內部名稱爲Created)進行排序:
1: <OrderBy>
2: <FieldRef Name='Author'/>
3: <FieldRef Name='Created' Ascending='FALSE' />
4: </OrderBy>
五、返回字段(欄)
進行查詢的時候,並不是每次都要返回條目的全部字段,出於性能考慮,能夠只返回所須要的一些字段,經過制定返回字段來實現這一點,指定返回字段的方式使用<FieldRef Name='字段名' />的形式。
例如,若是須要返回標題、做者和建立時間三個字段,則寫法爲:
1: <FieldRef Name='Title' />
2: <FieldRef Name='Author' />
3: <FieldRef Name='Created' />
這裏一樣須要使用字段的內部名稱。