LINQ to SharePoint
步骤
- 使用SPMetal导出SPList实体模型(cs文件)。默认情况下,此工具会将SPWeb级别下的所有列表、文档库等内容导出成实体模型。也可以通过编写XML,使其只生成指定的内容。
- 将步骤1中的文件添加到VS项目中,并添加引用
Microsoft.SharePoint.Linq。
完成以上两步,就可以使用LINQ查询SPList了。例:
using (DemoSiteDataContext context = new DemoSiteDataContext(SPContext.Current.Web.Url))
{
var result = from p in context.TESTLIST
where p.标题 != "AAA"
select p;
//var result2 = context.TESTLIST.Where(p => p.标题 != "AAA"); //Lambda表达式
List<TESTLIST项目> list = result.ToList();
}
关心的几个问题
-
效率和可用性
LINQ to SharePoint真正去SPList中取数据之前,实际上是将LINQ表达式或Lambda表达式转化成了CAML。所以,在一般情况下,性能应该是良好的。当然也有意外,当表达式无法转化CAML,或者无法准确地转化成CAML时,异常和性能问题也将会出现。
例:
var results = from projectItem in context.PriorityProjects
where projectItem.ExecutiveSponsor.Equals(sponsor) //string.Equals无法转化成<Eq>标签,这句表达式将会跳过此筛选条件而获取所有数据,再对结果集进行LINQ to Objects筛选,最终返回数据
//where projectItem.ExecutiveSponsor == sponsor //‘==’符号可以转化成<Eq>标签,将会转成带此标签的CAML对数据源进行筛选
select projectItem;
Linq to SharePoint与权限提升
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对象。
浙公网安备 33010602011771号