日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【转】4.2SharePoint服务器端对象模型 之 使用CAML进行数据查询(Part 2)

發(fā)布時(shí)間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】4.2SharePoint服务器端对象模型 之 使用CAML进行数据查询(Part 2) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

(三)使用SPQuery進(jìn)行列表查詢

1、概述

列表查詢主要是指在一個(gè)指定的列表(或文檔庫(kù))中按照某些篩選、排序條件進(jìn)行查詢。列表查詢主要使用SPQuery對(duì)象,以及SPList的GetItems方法,將SPQuery作為參數(shù)傳遞,返回查詢到的列表?xiàng)l目集合,即SPListItemCollection類型。

在使用SPQuery進(jìn)行列表查找的時(shí)候,其中一些屬性指定了其查找的特性:

Query屬性:通過該屬性指定CAML格式的篩選條件和排序條件(見上文),如果不指定,則默認(rèn)返回范圍內(nèi)的所有條目;

Folder屬性:通過該屬性指定在特定文件夾范圍內(nèi)進(jìn)行查找,如果不指定,則為列表或文檔庫(kù)的根文件夾;

RowLimit屬性:指定一次返回多少個(gè)條目,如果不指定,則返回所有條目;通過這個(gè)屬性與ListItemCollectionPosition屬性配合,可以實(shí)現(xiàn)列表?xiàng)l目的分頁(yè)查找;出于性能考慮,建議在一般情況下,都指定一個(gè)合理的RowLimit值,在SharePoint 2010中,系統(tǒng)也會(huì)自動(dòng)對(duì)查詢返回結(jié)果的數(shù)量上進(jìn)行一些限制和過濾(見后文關(guān)于查詢閾值的描述);

ViewFields屬性:指定CAML格式的返回字段(見上文),如果不指定,則默認(rèn)返回所有字段;

ViewAttributes屬性:這個(gè)屬性主要和Folder屬性配合使用,用于指定查詢范圍,如果不指定,則查找指定文件夾下的條目和子文件夾(詳見后文)。

下面是一個(gè)列表查詢的例子:

1: using(SPSite site = new SPSite("http://sp2010/book")) 2: { 3: using(SPWeb web = site.OpenWeb()) 4: { 5: SPList list = web.Lists["Chapters"]; 6: SPQuery query = new SPQuery(); 7: query.Query = "<Where><Contains><FieldRef Name='Title'/>" + 8: "<Value Type='Text'>sp</Value></Contains></Where>" + 9: "<OrderBy><FieldRef Name='Created'/></OrderBy>"; 10: query.ViewFields = "<FieldRef Name='Title'/>"; 11: SPListItemCollection items = list.GetItems(query); 12: foreach(SPListItem itm in items) 13: Console.WriteLine(Convert.ToString(itm["Title"])); 14: } 15: }

這是一個(gè)比較簡(jiǎn)單的列表查詢,查詢了“Chapters”這個(gè)列表的根目錄中,“標(biāo)題”字段包含字符串“sp”(SharePoint查詢中是否區(qū)分大小寫,由內(nèi)容數(shù)據(jù)庫(kù)的相關(guān)規(guī)則指定,默認(rèn)規(guī)則安裝的數(shù)據(jù)庫(kù)不區(qū)分字母的大小寫)的那些列表?xiàng)l目(可能還有文件夾),并輸出它們的標(biāo)題。

?

2、查詢范圍(Scope)

通過配合使用SPQuery的Folder屬性和ViewAttributes屬性,可以控制查詢時(shí)候的范圍。

首先需要說明的是,在進(jìn)行查詢的時(shí)候,普通列表?xiàng)l目(或者文檔庫(kù)中的文件)與文件夾是劃分查詢范圍的兩個(gè)重要條件。在查詢的時(shí)候,共有4種查詢范圍的設(shè)定:

  • 不指定ViewAttributes,則查詢的是Folder對(duì)應(yīng)的文件夾下面的列表?xiàng)l目(或文檔)以及子文件夾,就上面的例子來說,查詢的就是列表的根目錄,會(huì)返回根目錄中標(biāo)題包含“sp”的列表?xiàng)l目,以及名稱包含“sp”的子文件夾。
  • ViewAttributes = "Scope='FilesOnly'"。顧名思義,當(dāng)指定了這個(gè)范圍之后,查詢的就是Folder對(duì)應(yīng)文件夾下面的列表?xiàng)l目(或文檔)。如果把這個(gè)屬性加到上面的例子中,返回的將不再包括列表根目錄下的子文件夾——即使它們的名稱包含“sp”。
  • ViewAttributes = "Scope='Recursive'"。當(dāng)指定這個(gè)查詢范圍的時(shí)候,它查詢的范圍是Folder指定的文件夾及其子文件夾下的所有列表?xiàng)l目(或文檔),不管它們?cè)谀膫€(gè)子文件夾下。
  • ViewAttributes = "Scope='RecursiveAll'"。同樣的,它查詢的范圍是Folder指定的文件夾及其子文件夾下中的所有列表?xiàng)l目(或文檔)以及文件夾。

注意:當(dāng)查詢結(jié)果同時(shí)包含了文件夾和普通條目(或文檔)的時(shí)候,不論排序條件是如何指定的,在返回的結(jié)果中必然是文件夾在前、普通條目(或文檔)在后。

?

3、分頁(yè)查詢

如果列表中一次查詢返回的結(jié)果非常非常多,勢(shì)必會(huì)造成一定的性能損失,通過RowLimit屬性可以在一定程度上控制性能的降低,但是僅通過RowLimit屬性,就只能返回查詢結(jié)果中的前若干條結(jié)果,如果用戶想要再查看后面的結(jié)果,就要配合使用到SPQuery的ListItemCollectionPosition屬性進(jìn)行分頁(yè)查找。

在查找返回結(jié)果的SPListItemCollection對(duì)象中,有一個(gè)ListItemCollectionPosition屬性,包含了當(dāng)前查詢結(jié)果的分頁(yè)信息。將這個(gè)屬性傳遞到下一次查找過程中使用的SPQuery的對(duì)應(yīng)屬性中,就可以直接返回下一頁(yè)的查找結(jié)果,直到返回結(jié)果中的該屬性為null,就表示已經(jīng)查找到了最后一頁(yè)。每頁(yè)包含多少個(gè)結(jié)果由RowLimit屬性來指定。

下面的程序就是在之前程序的基礎(chǔ)上,增加了分頁(yè)查找的例子:

1: using(SPSite site = new SPSite("http://sp2010/book")) 2: { 3: using(SPWeb web = site.OpenWeb()) 4: { 5: SPList list = web.Lists["Chapters"]; 6: SPQuery query = new SPQuery(); 7: query.Query = "<Where><Contains><FieldRef Name='Title'/>" + 8: "<Value Type='Text'>sp</Value></Contains></Where>" + 9: "<OrderBy><FieldRef Name='Created'/></OrderBy>"; 10: query.ViewFields = "<FieldRef Name='Title'/>"; 11: query.RowLimit = 5; 12: SPListItemCollection items = null; 13: int currentPage = 1; 14: do 15: { 16: items = list.GetItems(query); 17: Console.WriteLine(string.Format("Page {0}:", currentPage)); 18: foreach(SPListItem itm in items) 19: Console.WriteLine(Convert.ToString(itm["Title"])); 20: query.ListItemCollectionPostion = 21: items.ListItemCollectionPosition; 22: currentPage++; 23: }while(items.ListItemCollectionPosition != null); 24: } 25: }

細(xì)心的讀者可能會(huì)注意到SharePoint內(nèi)置的列表視圖在進(jìn)行分頁(yè)的時(shí)候,只有上一頁(yè)和下一頁(yè)的鏈接按鈕,而沒有辦法直接跳轉(zhuǎn)到第x頁(yè),在翻到最后一頁(yè)之前,也沒有辦法知道在這個(gè)視圖下一共有多少個(gè)條目。在經(jīng)過上面的介紹之后,現(xiàn)在您應(yīng)當(dāng)已經(jīng)能想到這個(gè)現(xiàn)象背后的原因了。SharePoint內(nèi)置提供了如上面程序那樣向后翻頁(yè)的機(jī)制,讀者可以在前后翻頁(yè)的時(shí)候注意一下Url地址的變化,自行思考如何來實(shí)現(xiàn)“上一頁(yè)”的效果。實(shí)際上,在SharePoint 2003的時(shí)代,列表視圖里面就只有“下一頁(yè)”的按鈕,而沒有“上一頁(yè)”的按鈕。

?

4、通過查閱項(xiàng)進(jìn)行列表關(guān)聯(lián)查詢

在進(jìn)行列表查詢的時(shí)候,使用之前介紹的CAML語法,可以很容易地在一個(gè)列表中根據(jù)其中字段的不同篩選條件進(jìn)行查詢。但是從應(yīng)用的角度來講,僅將查詢局限在一個(gè)表中是遠(yuǎn)遠(yuǎn)不夠的,我們?cè)陂_發(fā)傳統(tǒng)應(yīng)用的時(shí)候必然會(huì)遇到多個(gè)表之間進(jìn)行關(guān)聯(lián)查詢的場(chǎng)景。這里我們就將介紹,在SharePoint中,如何實(shí)現(xiàn)這種多表之間關(guān)聯(lián)的查詢。

為了能夠更加清楚的說明問題,在這里我們不妨假定一個(gè)經(jīng)過簡(jiǎn)化后的實(shí)際場(chǎng)景:一個(gè)軟件銷售公司擁有自己的銷售人員列表,其中包含了銷售人員的姓名、擅長(zhǎng)的銷售領(lǐng)域等等;同時(shí)也擁有一張訂單列表,包含了所銷售的產(chǎn)品的名稱、數(shù)量、單價(jià),以及這張訂單的銷售人員的姓名。于是我們不難設(shè)計(jì)出如下的數(shù)據(jù)表結(jié)構(gòu):

在SharePoint中實(shí)現(xiàn)這樣的數(shù)據(jù)結(jié)構(gòu),我們可以想到創(chuàng)建“Sales”和“Orders”這兩個(gè)列表,并在“Orders”列表中創(chuàng)建一個(gè)“Saler”查閱項(xiàng)來查閱“Sales”列表的姓名字段,如下圖:

?

?

此時(shí),如果我們需要查找“張三”這個(gè)銷售賣出去的所有訂單,可以使用如下的CAML:

1: <Where><Eq> 2: <FieldRef Name='Saler' /> <!--注意這里使用了字段內(nèi)部名稱 --> 3: <Value Type='Lookup'>張三</Value> 4: </Eq></Where>

或者更準(zhǔn)確的(考慮到可能有多個(gè)名叫“張三”的銷售):

1: <Where><Eq> 2: <FieldRef Name='Saler' LookupId='TRUE' /> 3: <Value Type='Lookup'>1</Value> <!--1是我們關(guān)心的那個(gè)“張三”的ID--> 4: </Eq></Where>

于是,很自然地我們通過查閱項(xiàng)實(shí)現(xiàn)了最簡(jiǎn)單的兩個(gè)列表關(guān)聯(lián)查詢。

直到有一天,老板希望能夠查看一下那些專長(zhǎng)領(lǐng)域是Office的銷售都賣出過哪些訂單。按照一般的思路,我們可以先在銷售列表中找到那些專長(zhǎng)領(lǐng)域是Office的銷售有哪些,然后再分多次去訂單列表中查詢,最后把查詢結(jié)果拼在一起。但是有沒有更簡(jiǎn)單高效的方法呢?在SharePoint 2010中,為此提供了兩種方式:

方法一:使用SharePoint 2010查閱項(xiàng)新增的映射欄(Project Fields)的功能,將姓名、領(lǐng)域兩個(gè)字段同時(shí)映射到銷售列表中,見下圖:

?

?

于是,我們就可以使用映射到銷售列表中的“Sales:領(lǐng)域”這一字段進(jìn)行查詢了:

1: <Where><Eq> 2: <FieldRef Name='SalerField' /> <!--依然是字段的內(nèi)部名稱 --> 3: <Value Type='Lookup'>Office</Value> 4: </Eq></Where>

方法二:使用SharePoint 2010增加的SPQuery的列表關(guān)聯(lián)查詢功能。

這里,我們需要先借助SPQuery的Joins屬性聲明兩個(gè)列表的關(guān)聯(lián),再使用ProjectedFields屬性創(chuàng)建一個(gè)虛擬的映射字段,在這個(gè)虛擬字段上使用CAML進(jìn)行查詢。SPQuery的創(chuàng)建過程如下:

1: SPQuery query = new SPQuery(); 2:? 3: query.Joins = @"<Join Type='LEFT' ListAlias='Sales'> 4: <Eq> 5: <FieldRef Name='Saler' RefType='ID'/> 6: <FieldRef List='Sales' Name='ID'/> 7: </Eq> 8: </Join>"; 9:? 10: query.ProjectedFields = @"<Field Name='SalerField' Type='Lookup' 11: List='Sales' ShowField='Field'/>"; 12:? 13: query.Query = @"<Where><Eq> 14: <FieldRef Name='SalerField'/> 15: <Value Type='Lookup'>Office</Value> 16: </Eq></Where>";

在這段程序中,首先我們創(chuàng)建了一個(gè)列表關(guān)聯(lián)(Join),其類型是左外連接(Type=LEFT),并將這個(gè)關(guān)聯(lián)賦予一個(gè)列表別名(ListAlias='Sales'),關(guān)聯(lián)是建立在當(dāng)前列表(即訂單列表)的“Saler”字段(查閱項(xiàng),本質(zhì)是查閱ID)與Sales列表(這個(gè)名稱必須與Join中聲明的列表別名相同)的ID字段。實(shí)際上,這一段CAML如果“翻譯”成SQL語句的話(這里只是為了能夠讓傳統(tǒng)的開發(fā)人員更容易理解這段CAML,并不表示SharePoint實(shí)際存儲(chǔ)的數(shù)據(jù)表結(jié)構(gòu)。),看上去就變得熟悉多了:

1: Orders LEFT JOIN Sales 2: ON 3: Orders.Saler = Sales.ID

接下來,為了能夠在查詢條件中使用“領(lǐng)域”這一字段,需要把銷售表中的“領(lǐng)域”映射為訂單表中的一個(gè)虛擬字段(ProjectedField),并給這個(gè)字段隨意指定一個(gè)名稱(比如程序中的“SalerField”。該字段來自Sales列表(List='Sales',同樣要求與Join中定義的的列表別名相同)的“Field”字段(ShowField='Field',“領(lǐng)域”的內(nèi)部名稱),類型為查閱項(xiàng)(Type='Lookup')。

之后,我們就可以把這個(gè)映射字段“SalerField”當(dāng)作訂單列表中的字段在查詢使用了。

這兩種方法所達(dá)到的效果是完全一樣的,區(qū)別只是在于創(chuàng)建一個(gè)真正的映射字段,還是創(chuàng)建一個(gè)虛擬的映射字段。

由于我們的程序工作良好,為公司提高了效率,公司不斷壯大發(fā)展,在其它城市也成立了分部。此時(shí),為了能夠管理其他城市的銷售人員,我們的數(shù)據(jù)結(jié)構(gòu)就要發(fā)生變動(dòng)了,需要引入一張新的“城市”列表,并且在銷售列表上為每個(gè)銷售附加上城市的信息:

于是,在SharePoint中,我們也相應(yīng)的創(chuàng)建了一個(gè)城市列表,并且在銷售列表中創(chuàng)建了一個(gè)引用了城市列表的查閱項(xiàng):

這個(gè)時(shí)候,老板必定會(huì)希望能夠查看一下某個(gè)特定城市的所有訂單的銷售情況。當(dāng)然,我們?nèi)匀豢梢韵日业竭@個(gè)城市的所有銷售,然后分別查找出他們的訂單并把結(jié)果合并起來。不過在SharePoint 2010中,仍然有更直接的方法,那就是使用列表的關(guān)聯(lián)查詢。

遺憾的是,SharePoint的查閱項(xiàng)在映射多個(gè)列的時(shí)候,無法再?gòu)闹羞x擇一個(gè)查閱項(xiàng),因此我們只能通過方法二中的技術(shù)來實(shí)現(xiàn)這一需求。這個(gè)SPQuery的創(chuàng)建程序片段如下:

1: SPQuery query = new SPQuery(); 2:? 3: query.Joins = @"<Join Type='LEFT' ListAlias='Sales'> 4: <Eq> 5: <FieldRef Name='Saler' RefType='Id' /> 6: <FieldRef List='Sales' Name='ID' /> 7: </Eq> 8: </Join> 9: <Join Type='LEFT' ListAlias='Cities'> 10: <Eq> 11: <FieldRef List='Sales' Name='City' RefType='Id' /> 12: <FieldRef List='Cities' Name='ID' /> 13: </Eq> 14: </Join>"; 15:? 16: query.ProjectedFields = @"<Field Name='SaleCity' Type='Lookup' 17: List='Cities' ShowField='Title'/>"; 18:? 19: query.Query = @"<Where> 20: <Eq> 21: <FieldRef Name='SaleCity' /> 22: <Value Type='Text'>北京</Value> 23: </Eq> 24: </Where>";

?

?

?

與之前的程序相比,這段程序只是多做了一次Join,將關(guān)聯(lián)的列表從兩個(gè)變成了三個(gè),它“相當(dāng)于”如下的SQL語句(同樣,這里只是為了方便傳統(tǒng)的開發(fā)人員能夠理解SharePoint中的Join的寫法):

1: Orders LEFT JOIN Sales 2: ON 3: Orders.Saler = Sales.ID 4: LEFT JOIN Cities 5: ON 6: Sales.City = City.ID

程序的其他部分就不再贅述了。

我們可以看到,在SharePoint 2010中,列表查閱項(xiàng)的功能已經(jīng)有了極大的增強(qiáng),這代表著今天實(shí)現(xiàn)列表與列表之間的關(guān)聯(lián)越來越方便,可以更便捷地搭建出我們所需的應(yīng)用。不過也應(yīng)當(dāng)注意到,隨著關(guān)聯(lián)的日趨復(fù)雜,CAML的編寫也跟著越來越復(fù)雜,即使是很有經(jīng)驗(yàn)的程序員也難免在這個(gè)地方出現(xiàn)一些手誤,而這種錯(cuò)誤在程序調(diào)試過程中又是很難發(fā)現(xiàn)的。好在SharePoint 2010為我們提供了一項(xiàng)新的查詢技術(shù),我們將在下一節(jié)中對(duì)其進(jìn)行詳細(xì)介紹。

?

5、列表查詢的注意事項(xiàng)

在進(jìn)行列表查詢的時(shí)候,有一點(diǎn)是特別需要注意的,那就是在進(jìn)行不同列表的不同查詢條件的查詢情況下,必須每次重新構(gòu)造SPQuery對(duì)象。換句話說,每做一次查詢(只要查詢條件不同),就要重新new一個(gè)SPQuery對(duì)象出來。否則,在程序運(yùn)行的時(shí)候,仍會(huì)以最初的條件進(jìn)行查詢。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的【转】4.2SharePoint服务器端对象模型 之 使用CAML进行数据查询(Part 2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。