【问题标题】:iterate a sharepoint list迭代一个共享点列表
【发布时间】:2009-06-08 16:13:10
【问题描述】:

在代码中如何访问列表,例如 sharepoint 中的“MyList”, 然后遍历此列表项并获取该列表中特定列的值,例如“URL”列?

【问题讨论】:

  • 您在站点内的功能/Web 部件中吗?还是您通过 Web 服务访问 SharePoint?

标签: c# sharepoint


【解决方案1】:

要从列表中检索所有项目并遍历每个项目,最佳解决方案如下(假设此代码作为功能的一部分运行):

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    using(SPSite site = properties.Feature.Parent as SPSite)
    {
        SPList list = site.RootWeb.Lists["ListName"];
        SPListItemCollection items = list.Items;

        foreach (SPListItem listItem in items)
        {
            Response.Write(SPEncode.HtmlEncode(listItem["Url"].ToString()) +"<BR>");
        }
    }
}

但如果列表很大,最好通过列表项进行分页:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    using(SPSite site = properties.Feature.Parent as SPSite)
    {
        SPList list = site.RootWeb.Lists["ListName"];

        if(items.ItemCount > 100)
        {        
            SPQuery query = new SPQuery();
            query.RowLimit = 100;
            int index = 1;

            do
            {
                SPListItemCollection items = list.GetItems(query);

                foreach (SPListItem listItem in items)
                {
                    Response.Write(SPEncode.HtmlEncode(listItem["Url"].ToString()) +"<BR>");
                }

                query.ListItemCollectionPosition = items.ListItemCollectionPosition;
                index++;

            } while (query.ListItemCollectionPosition != null);
        }
        else
        {
            SPListItemCollection items = list.Items;

            foreach (SPListItem listItem in items)
            {
                Response.Write(SPEncode.HtmlEncode(listItem["Url"].ToString()) +"<BR>");
            }
        }
    }
}

这是基于微软的Best Practices for SharePoint

【讨论】:

    【解决方案2】:

    来自this blog post

    正确的做法是将 Items 属性返回值存储在 SPListItemCollection 变量中。这样,数据库只被查询一次,然后我们将遍历存储在集合对象中的结果集。这是更改后的示例代码:

    SPListItemCollection items = SPContext.Current.List.Items;
    for(int i=0;i<100 && i<items.Count;i++) {
      SPListItem listItem = items[i];
      htmlWriter.Write(listItem["Title"]);
    }
    

    【讨论】:

    • 如果我想访问不在当前上下文中的列表怎么办?
    【解决方案3】:

    您也可以直接迭代项目,如果您使用的是 URL 字段,您可能希望使用 SPFieldUrlValue 类,因此您不必处理 SharePoint 存储 URL 的方式:

    foreach(SPListItem item in spList.Items){
      SPFieldUrlValue data = item["Url"] as SPFieldUrlValue;
      // now you have data.Description, data.Url
    }
    

    有很多这样的SPField* 辅助类,它们非常有用,特别是当您有多个值时。


    编辑:

    出于某种原因,有些人认为这种方式比较慢,基于 Greg 帖子的博客文章中的证据(甚至被否决了)。然而,这与我的回答无关:foreach 循环创建了一个迭代器,因此它不应再访问数据库 99 次(在他们使用for 循环访问前 100 个项目的帖子中) .

    【讨论】:

    • 如果列表很大,这种技术会给你带来麻烦。参考。 Items 集合导致与要从 DB 检索的列表关联的所有记录。除非列表很小,否则这不是问题。
    • 好的,这绝对是迭代 Sharepoint 列表的错误方法,正如 Microsoft 最佳实践中所指出的 - 请参阅 msdn.microsoft.com/en-us/library/…。有关详细信息,请参阅本文:lots-with-sharepoint.blogspot.com/2009/01/… -1 答案不佳。
    • @MagicAndi - 现在,这更好,至少你有充分的理由投反对票。实际上,您可以将其添加为答案,因为 OP 确实要求提供特定列。
    • 我仍然不相信这不是正确的答案。链接的文章并没有真正解决这个问题,除非我遗漏了什么。
    【解决方案4】:

    如果您在某个功能中,该功能会在特定范围内激活(例如站点、Web、WebApplication 或 Farm)。

    如果您想从功能访问列表,请使用 SPFeatureReceiver 类将事件接收器绑定到您的功能。然后,在该类中,当功能激活事件被触发时,会有覆盖。覆盖接收 SPFeatureReceiverProperties 类型的参数。

    通过该参数,您可以使用 get 进入站点:

    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
      using(SPSite site = properties.Feature.Parent as SPSite) //this depends on scope of feature
      {
        SPList myList = site.RootWeb.Lists["MyList"];
      }
    }
    

    有关如何迭代该列表,请参阅其他答案

    【讨论】:

      【解决方案5】:

      我知道这个问题很久以前就被问过了,但我希望我现在能够帮助别人:)

      这就是我能够做到这一点的方式,

      protected void Page_Load(object sender, EventArgs e)
          {
              // Get the current domain 
              var current = HttpContext.Current.Request.Url.Host;
      
              // We need to tell the SPSite object the URL of where our List is stored.
              // Make sure you have the right location placed after the 'current' variable
              using (SPSite spSite = new SPSite("http://"+current+"/DirectoryForLists/Lists")) 
              {
                  // Returns the Web site that is located at the specified server-relative or site-relative URL.
                  using (SPWeb spWeb = spSite.OpenWeb())
                  {
                      //Get our list we created.
                      SPList list = spWeb.Lists["Name Of the List"];
      
                      // Create a new SPQuery object that will hold our CAML query.
                      SPQuery q = new SPQuery();
                      // CAML query.
                      // This allows you to controll how you receieve your data.
                      // Make the data ASC or DESC. Find more on MSDN.
                      q.Query = "<OrderBy><FieldRef Name='DESCR' Ascending='TRUE' /></OrderBy>";
      
                      // We put our list data into a SP list Item Collection.
                      // Notice that the CAML query is the only parameter for the GetItems() function.
                      SPListItemCollection items = list.GetItems(q);
      
                      // Here you can loop through your list.
                      foreach (SPListItem spItem in items)
                      {
                          // Your code here.
                          MessageBox(spItem);
      
                          // Get URL column
                          MessageBox(spItem["URL"]);
      
                          // Another Column
                          MessageBox(spItem["DateTime"]);
                      }
                  }
              }
          }
      

      【讨论】:

      • 如果你对我投了反对票,请告诉我原因。这个解决方案确实有效。
      【解决方案6】:

      下面是迭代的最佳选择

          SPList list = web.Lists[listname];
      
          SPQuery query = new SPQuery();
          query.Query = "<OrderBy><FieldRef Name='ID' /></OrderBy>";
          //Scope="Recursive" retrieves items from all folders and subfolders in a list
          query.ViewFields = "<FieldRef Name='" + Lists.MRPLibrary.RebateClaimed + "' /><FieldRef Name='ID'/>";
          query.ViewAttributes = "Scope=\"RecursiveAll\"";
          query.RowLimit = 100;
      
          do
          {
              SPListItemCollection items = list.GetItems(query);
      
              foreach (SPListItem listItem in items)
              {
      
              }
      
              query.ListItemCollectionPosition = items.ListItemCollectionPosition;
      
          } while (query.ListItemCollectionPosition != null);
      
      }
      

      【讨论】:

        【解决方案7】:

        以下代码用于删除所有批量列表项,此处可以跳过最近的 150 个要删除的项。 遍历 SPListItemCollection 和非常快的时间,比如 3000 个项目将在 2 分钟内被删除。

        SPList list = web.Lists["DemoDelete"];
        
        SPListItemCollection collListItems = list.GetItems();
        var watch = System.Diagnostics.Stopwatch.StartNew();
        Console.WriteLine("Start Time: " + watch);
        //delete all items uncomment this code
        //foreach (SPListItem item in collListItems)
        //{
        //    SPListItem delItem = list.GetItemById(item.ID);
        //    Console.WriteLine("Item Deleted" + delItem.ID);
        //    delItem.Delete();
        //    list.Update();
        //}
        //skip lastest 150 items
        for (int i = collListItems.Count - 150; i >= 0; i--)
        {
        SPListItem listItem = list.GetItemById(collListItems[i].ID);  //collListItems[i];
        Console.WriteLine("Item Deleted" + listItem.ID);
        listItem.Delete();
        list.Update();
        }
        
        watch.Stop();
        var elapsedMs = watch.ElapsedMilliseconds;
        Console.WriteLine("End Time: " + elapsedMs);
        

        【讨论】:

          【解决方案8】:

          正如其他人所说,您不应该直接迭代 Items 集合(尤其是在大型集合中)。这是一个替代方案:

          // 如果你需要整个集合。否则使用 SPQuery 就行了

          DataTable dt = list.Items.GetDataTable();
          
          foreach (DataRow row in dt.Rows)
          {
           ...
          

          然后你可以做很多事情。如果您需要进行检查以仅获取部分物品,例如:

             if (row["ContentType"].ToString().Equals("Your contenttype id"))
             {
             SPListItem item = list.GetItemById((int)row["ID"]);
          

          或使用 SpQuery 在查询中获取您的列,例如:

          SPQuery oQuery = new SPQuery();
          oQuery.ViewFields = "<FieldRef Name='UrlColumn'/>";
          
          list.Items.GetItems(oQuery).GetDataTable();
          
          ...foreach code...
          row["UrlColumn"] 
          

          【讨论】:

          • 这比迭代项目集合没有任何好处。问题仍然是你得到所有的列和所有的行。更糟糕的是数据集臃肿。
          【解决方案9】:

          如果您在 x86 环境中,我最近发现了一种非常棒的只读方式来使用 MSSQL/OLEDB 获取数据...

          SELECT * FROM OPENROWSET (
              'Microsoft.ACE.OLEDB.12.0',
              'WSS;IMEX=1;RetrieveIds=Yes;DATABASE=http://sharepoint.lsi.local/ops/;LIST={3DCAF100-44A1-4331-8328-748AA98E36AB};',
              'SELECT * FROM list'
          )
          

          http://www.connectionstrings.com/sharepoint

          【讨论】:

            【解决方案10】:

            顺便说一句 使用 OPENROWSET 时...

            IMEX=2 用于读/写。 IMEX=1 是只读的。

            List = [Name] 对我有用,而不需要使用 list={GUID}。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-09-04
              • 2018-12-01
              • 2021-06-12
              相关资源
              最近更新 更多