SharePoint 2013 应用开发实战
上QQ阅读APP看书,第一时间看更新

2.6 CAML和列表查询对象

前面的章节中介绍了如何通过对象模型获取列表的数据,但是在现实的环境中,一个列表的列表项数量可能是非常庞大的,如果通过SPList.Items的方式获取列表数据,是很低效的一种手段。在SQL数据库中,可以通过执行SQL查询语句来筛选数据,类似的,在SharePoint服务器端对象模型中,可以使用SPQuery对象、SPSiteDataQuery对象或LINQ to SharePoint提供程序来达到类似筛选的效果。

2.6.1 CAML

在介绍它们之前,先了解一下CAML的概念。

协作应用程序标记语言简称CAML,它是基于XML的,用来定义SharePoint网站和列表中的栏和视图,大小写敏感。它可以用来定义数据、呈现数据并在编程中使用。

读者可以参照SQL查询语句进行学习,CAML在查询中用到的内容相当于SQL语句中where之后的部分。通常一个完整的查询框架格式为下面所示样式结构:

    <Where>
     <And|Or>
         <Oper>
             …
     </Oper>
    </And|Or>
    </Where>
    <GroupBy>…</GroupBy>
    <Orderby></OrderBy>
    <ViewFields></ViewFields>
    <RowLimit></RowLimit>

条件运算符有And和Or,分别是并且和或者的意思。这里有一点需要注意,一个条件运算符至多只能包含两个操作运算符,超过是无效的。举例来说,当有三个操作Oper1、Oper2和Oper3是并且关系时,正确的写法是:

    <Where>
    <And>
    <And>
    <Oper1>
    </Oper1>
    <Oper2>
    </Oper2>
    </And>
    <Oper3>
    </Oper3>
    </And>
    </Where>

常用的比较运算符如表2-1所示。

表2-1 常用的CAML比较运算符

读者可以访问https://msdn.microsoft.com/zh-cn/library/ms467521.aspx查看最新的运算符说明。

2.6.2 SPQuery和SPSiteDataQuery对象

SPQuery对象模型用来在查询列表数据时构建一个查询条件,返回满足条件的列表项的集合。还是以前面章节的自定义列表为例,下面的代码展示了如何查询列表项中标题栏包含A的列表项的集合:

    using (SPSite site = new SPSite("http://<mysiteurl>/subSite"))
    {
              using (SPWeb web = site.OpenWeb())
             {
                     SPList customList = web.GetList("/Lists/List/");
                     SPQuery query = new SPQuery();
                     query.Query = @"<Where>
    <Contains>
    <FieldRef Name='Title' />
    <Value Type='TEXT'>A</Value>
    </Contains>
    </Where>";
                     query.RowLimit = 10;
                     SPListItemCollection queryItems = customList.GetItems(query);
                     foreach (SPListItem item in queryItems)
                     {
                         Console.WriteLine(string.Format("Item Title: {0}",
item.Title));
                     }
             }
    }

执行结果将只输出自定义列表中标题包含A的列表项。

SPQuery只能在单一列表内进行使用,如果想在网站集的范围内查询某一类型多个列表项数据,就需要用到SPSiteDataQuery对象了。笔者在网站中新建另一个自定义列表来演示该对象的用法,在新的自定义列表中新建一个列表项叫做A+,如图2-21所示。

图2-21 新的自定义列表

现在需要查询出SharePoint网站的所有自定义列表中列表项标题包含A的集合,代码如下所示:

    using (SPSite site = new SPSite("http://<mysiteurl>/subSite"))
    {
              using (SPWeb web = site.OpenWeb())
              {
                    SPSiteDataQuery siteQuery = new SPSiteDataQuery();
                    siteQuery.Lists = "<Lists ServerTemplate=\"100\" />";
                    siteQuery.ViewFields = "<FieldRef Name=\"Title\" />";
                    siteQuery.Query = @"<Where>
    <Contains>
    <FieldRef Name='Title' />
    <Value Type='TEXT'>A</Value>
    </Contains>
    </Where>";
                    DataTable dataTable = web.GetSiteData(siteQuery);
                    foreach (DataRow dataRow in dataTable.Rows)
                    {
                       Console.WriteLine(string.Format("Item Title: {0}",
dataRow["Title"]));
                    }
              }
    }

其中SPSiteDataQuery.Lists属性指定了要查询哪一类列表,这么写是因为自定义列表的模板ID为100。在SharePoint中,不同类型的列表具有不同的模板ID,读者可以通过在网站上添加列表→高级选项时通过查看浏览器的URL得到这个模板ID,如图2-22所示。

图2-22 自定义列表的模板ID

执行结果将输出“公告A”和“A+”,如图2-23所示。

图2-23 SPSiteDataQuery执行的输出结果

虽然CAML语句比较容易理解,但是跟SQL语句相比,尤其是查询条件复杂时,是很容易出错的,笔者建议尽量使用CAML工具(如CAML Designer、CAML Builder)来构建CAML查询语句。

2.6.3 LINQ to SharePoint

查询列表数据的另一种方式是使用LINQ语法查询SharePoint列表。LINQ to SharePoint是始于SharePoint 2010的新特性,它使用类型化的方式访问列表,类似访问数据库,更容易被习惯和接受。

LINQ to SharePoint的本质仍然是利用CAML查询,LINQ to SharePoint提供的程序是在Microsoft.SharePoint.Linq命名空间中被定义,它会自动将LINQ转换成CAML查询。所以,开发人员无须再去了解如何编写CAML查询语句,提升了开发人员的效率。

使用LINQ to SharePoint可以实现列表项的增删改查操作,笔者推荐使用实体类生成工具SPMetal生成SharePoint网站中列表的实体类,虽然可以手写实体类,但这毕竟增大了出错的几率,而且操作起来较为烦琐。有高效的手段,何乐而不为呢?

学习这部分时,读者可以类比Entity Framework,它们的共性是都根据现有数据生成实体类以方便开发人员做处理。

SPMetal工具位于SharePoint服务器的C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\BIN目录下,如图2-24所示。

图2-24 SPMetal工具的物理路径

使用如下操作可以生成网站的内容实体模型:

(1)以管理员身份运行命令提示符,输入cd C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\BIN进入到SPMetal工具所在文件夹。

(2)执行命令spmetal.exe /web:<your sharepoint site url> /code:C:\WebDataEntities.cs,执行成功后将在C盘根目录生成实体类文件WebDataEntities.cs。

开始编写代码之前,首先在项目中添加Microsoft.SharePoint.Linq的引用,然后右击项目节点,选择添加→现有项,选择生成的CS文件添加到项目中。

准备工作完成了,下面将通过代码带领读者一步一步了解如何利用LINQ to SharePoint实现基本操作,还是以网站中的自定义列表为例。

获取列表项并输出的代码如下所示:

    using (WebDataEntitiesDataContext ctx = new
WebDataEntitiesDataContext("http://<mysiteurl>/subSite"))
    {
              var items = ctx.自定义列表.Where(p=>p.标题.Contains("A")).ToList();
              foreach (自定义列表项目 item in items)
              {
                     Console.WriteLine(string.Format("Item Title: {0}.", item.标
题));
              }
    }

运行结果和之前的一样,由于笔者使用的是中文的环境,而SPMetal工具根据名称生成相应的实体类,所以代码中出现了中文。

添加、修改、删除列表项的代码如下所示。

添加列表项:

    using (WebDataEntitiesDataContext ctx = new
WebDataEntitiesDataContext("http://<mysiteurl>/subSite"))
    {
              自定义列表项目 newItem = new 自定义列表项目();
              newItem.标题 = "公告C";
              newItem.公告内容 = "公告C的内容";
              ctx.自定义列表.InsertOnSubmit(newItem);
              ctx.SubmitChanges();
    }

修改列表项:

    using (WebDataEntitiesDataContext ctx = new
WebDataEntitiesDataContext("http://<mysiteurl>/subSite"))
    {
             自定义列表项目 itemToModify = ctx.自定义列表.Where(p => p.Id ==
5).FirstOrDefault();
             if (itemToModify!= null)
             {
                   itemToModify.标题="公告C改";
                   itemToModify.公告内容 = "公告C的内容改";
             }
             ctx.SubmitChanges();
    }

删除列表项:

    using (WebDataEntitiesDataContext ctx = new
WebDataEntitiesDataContext("http://<mysiteurl>/subSite"))
    {
             自定义列表项目 itemToDelete = ctx.自定义列表.Where(p => p.Id ==
5).FirstOrDefault();
             if (itemToDelete != null)
             {
                   ctx.自定义列表.DeleteOnSubmit(itemToDelete);
             }
             ctx.SubmitChanges();
    }

以上便是LINQ to SharePoint在应用上的基本操作实例,尤其是查询部分,比SPQuery的CAML查询要灵活简便得多,推荐使用这种方式进行列表的查询等操作。在使用时要注意数据结构的一致性,否则可能会导致异常错误。