zoukankan      html  css  js  c++  java
  • SharePoint 2010中新增的GetItemByIdSelectedFields方法

    唔……事先声明,其实这篇文章没有太多实际的使用意义,所以想了解某个东东怎么用的同学可以按Alt + F4(或者Ctrl + W)了。想了解SharePoint里面是怎么工作的同学可以继续往下翻。

    最近正在和KB一起写关于SharePoint 2010开发方面的一本书,在研究2010新增加的对象模型的时候,偶然发现了这个方法。我们都知道在2003/2007里面,根据ID获取列表条目使用的是SPList的GetItemById方法(什么,没听说过这个方法?那恐怕你不是一个合格的SharePoint开发人员……)。新增加的这个方法名字叫GetItemByIdSelectedFields(同时也增加了一个GetItemByIdAllFields的方法与之作伴,不过这个和GetItemById是完全等效的,就不再废话了),方法的定义是这样的:

       1: public SPListItem GetItemByIdSelectedFields(int id, params string[] fields)

    当我第一眼看到这个的时候,立刻就想到了SPQuery的那个ViewFields属性,获取某个列表条目的时候,只返回某些指定的字段,来提高效率。可是当我写了个Console程序试验的时候,发现并不是我想象中的样子,比如我写成(这个方法要求写内部名称):

       1: SPListItem item = spList.GetItemByIdSelectedFields(1, "Title", "Created");
       2: Console.WriteLine(item["Modified"]);

    这段程序居然没有报错,而且Modified的值也正常返回了,于是我试了试,一个自定义列表里面居然有50来个字段的值都正常返回了,但是所有的查阅项、用户和用户组(其实这个本质上也是查阅项)都没有返回。

    在好奇驱使下(暂时还害不死我),我Reflector了一下这个方法的源代码:

       1: if(field == null)
       2: {
       3:   throw new ArgumentNullException("fields");
       4: }
       5:  
       6: StringBuilder builder = new StringBuilder();
       7: foreach (string str in fields)
       8: {
       9:   if (str != null)
      10:   {
      11:     builder.Append("<FieldRef Name=\"" + str + "\"/>");
      12:   }
      13: }
      14:  
      15: foreach (SPField field in this.Fields)
      16: {
      17:   bool flag = false;
      18:   foreach (string str2 in fields)
      19:   {
      20:     if (str2 == field.InternalName)
      21:     {
      22:       flag = true;
      23:       break;
      24:     }
      25:   }
      26:   if (!flag && field.MustFetchByDefault)
      27:   {
      28:     builder.Append("<FieldRef Name=\"");
      29:     builder.Append(field.InternalName);
      30:     builder.Append("\"/>");
      31:   }
      32: }
      33:  
      34: return this.GetItemById(id, null, false, builder.ToString());

    关于最后那个GetItemById是怎么回事,暂时先不用再去深究了,只要知道它是一个GetItemById的重载,目的就是查找条目用的就行了,最后一个参数把需要获取的字段以CAML的形式放进去。

    第7行那个foreach很好理解,把我们需要的字段加进去;但是第15行的那个foreach一开始就有点让人摸不着头脑了,还要把其他字段也放进去?而且SPField的这个MustFetchByDefault是什么东西?再挖挖看看:

       1: internal bool MustFetchByDefault
       2: {
       3:   get
       4:   {
       5:     string fieldAttributeValue = this.GetFieldAttributeValue("List");
       6:     if(!string.IsNullOrEmpty(fieldAttributeValue) &&
       7:        (fieldAttrbuteValue != GlobalList.Docs.ToString()))
       8:     {
       9:       return false;
      10:     }
      11:     return true;
      12:   }
      13: }

    如何判断一个字段是不是要取呢?通过判断字段的一个List属性,至于GetFieldAttributeValue方法就不再往上贴了(否则有骗字数的嫌疑),总之它是从Field的类似SchemaXml属性(字段描述)的Xml结点中,去找一个List的属性。如果找到了,而且不是GlobalList.Docs(某个特殊的东东)的话,那么这个字段就不是必须的,换句话说这个字段我就不用返回给用户。

    那什么字段的SchemaXml里会有List属性?一个字段里有一个和列表的属性?查阅项!哈,真的是回避掉了所有的查阅项。(Docs这个东西是“路径”这个字段的List属性,估计有某些特殊的来源)

    现在我们知道为什么会包含其他所有字段,并且不包含查阅项了。但是为什么要这样?如果我们对SharePoint的内容数据库有所了解的话,我们会知道其实查阅项在内容数据库里只存了一个ID值在AllUserData表里面(但是用对象模型取出来的时候,是包含查阅那个条目相应字段的内容的),这也就意味着,如果要返回查阅项的值,就需要多做一些额外的数据库操作(比如再去找到被查阅的那个条目,把相应字段的值返回来,拼装成“1;#Administrator“这种鬼样子)。更重要的是,如果这个查阅项是一个多值的,那么这个查阅项本身都是保存在另外一个表中的(AllUserDataJunctions),这样要返回起来还真是要费不少功夫。所以2010里面新增加了这么一个东西,如果我们的列表中包含好多个查阅项,而我们可能暂时只用到其中一两个(或者一个都不用)的话,看来用这个方法确实能提高不少效率。

  • 相关阅读:
    spring-cloud-gateway动态路由
    spring-cloud-gateway静态路由
    activiti6官方示例笔记
    spring-cloud-gateway过滤器实践
    spring-cloud-gateway简介
    设计模式--策略模式
    学习ConcurrentHashMap1.7分段锁原理
    SpringBoot Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
    MYSQL触发器的使用
    储存过程 (创建,调用,查询,删除)
  • 原文地址:https://www.cnblogs.com/erucy/p/2416090.html
Copyright © 2011-2022 走看看