SharePoint 2010支持Linq to SharePoint,讓程序員可以使用Linq語法直接訪問SharePoint 2010網站中的數據。但是在默認情況下,Linq to SharePoint不支持權限提升,也就是說,如果在代碼中嘗試通過SPSecurity.RunWithElevatedPrivileges()方法來提升執行權限,你可能會發現,代碼並不會如你所願的以系統帳戶的身份,訪問SharePoint網站的數據。
下面是一段典型的權限提升的代碼,在匿名委託方法中,首先構造了新的SPSite和SPWeb對象,然後使用Linq to SharePoint查詢了一個列表中所有列表項的標題。雖然看起來Linq to SharePoint好像會被提升它執行的權限,但實際情況並非如此。在下面的代碼中,中間的Linq to SharePoint代碼並不會受到外面調用SPSecurity.RunWithElevatedPrivileges()方法的影響。
private IEnumerable<String> GetAllHardwareNames()
{
var currentWebUrl = SPContext.Current.Web.Url;
List<String> result = null;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (var site = new SPSite(currentWebUrl))
{
using (var web = site.OpenWeb())
{
using (var ctx = new ContosoDataContext(currentWebUrl))
{
var names = from h in ctx.硬件資產跟蹤
select h.標題;
result = names.ToList();
}
}
}
});
return result;
}
如果希望Linq to SharePoint代碼能夠提升它的執行權限,在使用Linq to SharePoint之前,需要做一個比較trick的事情,那就是將當前HttpContext對象設置爲null。下面的代碼中,使用粗體標識了這些特殊的代碼。
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (var site = new SPSite(currentWebUrl))
{
using (var web = site.OpenWeb())
{
var httpContext = HttpContext.Current;
HttpContext.Current = null;
using (var ctx = new ContosoDataContext(currentWebUrl))
{
var names = from h in ctx.硬件資產跟蹤
select h.標題;
result = names.ToList();
}
HttpContext.Current = httpContext;
}
}
});
只所以要使用這個技巧,是因爲在Linq to SharePoint的實現中,使用了一個名爲Microsoft.SharePoint.Linq.Provider.SPServerDataConnection的類,來真正連接到SharePoint網站。在這個類的構造函數中,有類似這樣的代碼:
if (SPContext.Current != null)
{
this.defaultSite = SPContext.Current.Site;
this.defaultWeb = (SPContext.Current.Web.Url == url) ? SPContext.Current.Web : this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
}
else
{
this.defaultSite = new SPSite(url);
this.defaultWeb = this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
}
爲了提高性能,它會優先重用SPContext對象中所緩存的SPWeb和SPSite對象。這個行爲雖然可以提高代碼的運行效率,但是卻會導致權限提升的失效,因爲提升了權限的代碼必須使用一個新構造的SPSite和SPWeb對象。