SharePoint服務器端對象模型 之 使用LINQ進行數據訪問操做(Part 4)

(六)高效合理的使用LINQapp

一、DataContext中的兩個屬性ide

爲了可以使用DataContext進行數據提交,在DataContext進行數據查詢和操做的過程當中,內部會進行數據狀態的保持和追蹤,這會帶來一些額外的開銷。若是用戶僅須要進行數據讀取的話,能夠經過將DataContext的ObjectTrackingEnabled屬性設爲false(默認值爲true)來避免這些維護數據狀態帶來的額外開銷。工具

此外,在DataContext中還有一個DefferedLoadingEnabled屬性,用於控制數據實體之間的引用(對應到SharePoint列表中即查閱項)是否加載。若是將此屬性設置爲false(默認值爲true),那麼在返回結果以後,全部的查閱項引用都不會加載,值爲null。所以,若是不須要使用其中查閱項類型內容的話,能夠將此屬性設置爲false,能夠進一步提升查詢速度。網站

二、LINQ中的運算spa

在針對其餘數據源進行查詢的時候,LINQ能夠進行多種運算,可是因爲在SharePoint中,查詢最終是使用CAML進行的,所以有些運算在LINQ to SharePoint中是不支持的,或者在執行效率上有所區別。code

高效查詢(Efficient Queries)對象

在LINQ to SharePoint中,凡是能夠直接被轉換成CAML查詢的LINQ查詢,都被稱爲高效查詢。系統會將CAML查詢的結果直接轉換成相應的數據實體。ip

不支持的查詢內存

在LINQ中,不支持查詢嵌套,即將一個查詢的結果做爲另一個查詢的查詢條件(在傳統的T-SQL中,也就是select語句的嵌套)。ci

此外,在LINQ to SharePoint中,對兩個查詢結果的集合操做也是不被支持的,例以下面的程序會拋出異常:

   1: var orders1 = from o in ctx.InteralOrder
   2:               select o;
   3: var orders2 = from o in ctx.ExternalOrder
   4:               select o;
   5: var total = orders.Union(orders2);  // Exception Here!

可是經過使用ToList方法將結果轉換成List以後,就能夠進行集合運算了:

   1: var orders1 = from o in ctx.InteralOrder
   2:               select o;
   3: var orders2 = from o in ctx.ExternalOrder
   4:               select o;
   5: var total = orders.ToList().Union(orders2.ToList());  //OK Now.

半高效查詢(Semi-Efficient Queries)

在有些狀況下,查詢條件能夠被直接轉換成CAML進行,可是在返回結果的時候,卻沒法轉換成相應的CAML。考慮下面兩個例子:

   1: // 查詢1:
   2: var chapters = from chp in ctx.Chapters
   3:                where chp.Writer == "Erucy"
   4:                select new {chp.Name, chp.WordCount};
   5:  
   6: // 查詢2:
   7: var chapters = from chp in ctx.Chapters
   8:                where chp.Writer == "Erucy"
   9:                select new {chp.Name, Pay = chp.WordCount * 0.05};
在這兩個查詢中,查詢條件能夠直接轉換成:
   1: <Where>
   2:   <Eq>
   3:     <FieldRef Name='Writer'/>
   4:     <Value Type='Text'>Erucy</Value>
   5:   </Eq>
   6: </Where>

在查詢1中,查詢結果能夠直接用CAML的ViewFields來表示:

   1: <ViewFields>
   2:   <FieldRef Name='Name' />
   3:   <FieldRef Name='WordCount' />
   4: </ViewFields>

因而,LINQ to SharePoint即可以直接將返回結果轉換成相應的數據實體對象。

可是在查詢2中,返回結果的「WordCount * 0.05」部分因爲涉及到了運算,沒法直接使用CAML進行描述,所以LINQ to SharePoint在返回這類查詢結果的時候,須要在CAML查詢結果的基礎之上,再利用LINQ to Objects進行一次結果轉換,可是在轉換過程當中不須要再涉及查詢操做。這種查詢實際上至關於以下代碼:

   1: var camlResult = from chp in ctx.Chapters
   2:                  where chp.Writer == "Erucy"
   3:                  select new {chp.Name, chp.WordCount};
   4: var chapters = from chp in camlResult
   5:                select new {chp.Name, Pay = chp.WordCount * 0.05};

除去這種簡單運算以外,在返回結果的時候,LINQ查詢中所使用到的Distinct、Average、Sum、Max、Min等操做都屬於這一類型。因爲這種查詢須要兩個階段來完成,所以也被稱爲兩階段查詢(Two-Stage Queries)。

低效查詢(Inefficient Queries)

在上面的例子中,僅是在返回結果的時候須要進行額外的轉換,而查詢自己仍然可使用CAML進行。而在有些狀況下,查詢徹底沒法轉換成CAML格式,而這個時候,LINQ to SharePoint會首先獲取到列表中全部內容,將其轉換爲類型,在此基礎上再進行LINQ to Objects的查詢,使得SharePoint數據查詢徹底退化成內存中的數據查詢。這種查詢也須要使用兩個階段來完成操做,但因爲須要獲取列表中的所有數據,效率較低。

這種查詢能夠實現一些CAML沒法實現的功能。在CAML查詢中,只支持字段欄與具體數值之間的比較運算,但不支持字段欄與字段欄之間的運算,例以下面的這個查詢:

   1: var okOrders = from order in ctx.Orders
   2:                where order.Sale > order.Quota
   3:                select order;
在實際查詢的時候,因爲CAML不支持在兩個字段之間進行比較,所以這個查詢最終會退化爲在內存中的對象查詢:
   1: var okOrders = from order in ctx.Orders.ToList()
   2:                where order.Sale > order.Quota
   3:                select order;

(ToList方法會將EntityList退化成普通的List,將Orders列表中的全部數據都載入內存,再進行查詢)

三、LINQ to SharePoint所不支持的場景

雖然LINQ to SharePoint在進行數據查詢、數據操做的時候提供了無比的便利性,可是並不是是全部場景均可以使用LINQ。除去上面提到的不支持的運算外,下面列出了幾種常見的默認狀況下不能使用LINQ to SharePoint的場景:

  • 沒法查詢外部列表(External List)和外部內容類型(External Content Type)。SPMetal工具不會爲這些類型的數據生成數據實體類。不過查詢外部數據可使用相應的其餘類型的LINQ Provider,如LINQ to SQL、LINQ to XML等。
  • 在Web上只能查詢當前網站的內容。因爲在DataContext中某些地方用到了當前的上下文信息(HttpContext),所以在Web上(好比Web部件),LINQ to SharePoint默認狀況下只能對當前程序所在網站的內容進行查詢。
  • 不支持匿名網站。LINQ to SharePoint目前仍不支持網站的匿名訪問(即便網站開啓了匿名訪問支持)。
相關文章
相關標籤/搜索