迭代一个SharePoint列表

6

在代码中,我如何访问SharePoint中的列表(例如"MyList"),然后遍历该列表项并获取该列表上特定列(例如"URL"列)的值?


你是在站点的功能/ Web 部件中吗?还是通过 Web 服务访问 SharePoint? - d4nt
10个回答

3
为了从列表中检索所有项并迭代每个项,最好的解决方案如下(假设此代码作为功能的一部分运行):
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>");
            }
        }
    }
}

这是基于微软的“SharePoint最佳实践”(Best Practices for SharePoint)所述的。

2

根据这篇博客文章

正确的方法是将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"]);
}

如果我想访问当前上下文中不存在的列表怎么办? - contactmatt

1

您也可以直接迭代项,如果您使用的是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个项目)。


8
如果列表很大,这种技术会让你陷入麻烦。引用Items集合将导致检索与列表相关的所有记录从数据库中检索出来。除非列表很小,否则就会成为问题。 - Jeff
3
根据微软最佳实践指南(http://msdn.microsoft.com/en-us/library/bb687949.aspx#WorkingWithFoldersLists),这种迭代Sharepoint列表的方法是完全错误的。请参阅此文章(http://lots-with-sharepoint.blogspot.com/2009/01/best-practices-sharepoint-object-model_6154.html)以获取更多详细信息。这个回答很差,扣1分。 - Tangiest
@MagicAndi- 现在好多了,至少你有充分的理由给出负评。实际上,您可以将其添加为答案,因为OP确实要求特定列。 - Kobi
我仍然不相信这不是正确答案。链接的文章似乎并没有真正解决这个问题,除非我漏看了什么。 - Jussi Palo

0
以下是迭代的最佳选项
    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);

}

0
以下代码用于删除所有批量列表项,可以跳过最新的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);

0

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

这是我如何完成这个任务的方法,

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"]);
                }
            }
        }
    }

1
如果你给我点踩,请告诉我原因。这个解决方案确实有效。 - IE5Master

0

如果您正在使用功能,则该功能在特定范围(例如站点、Web、WebApplication或Farm)上激活。

当您想要从功能访问列表时,请使用SPFeatureReceiver类将事件接收器绑定到您的功能。然后,在该类中,有针对触发功能激活事件的重写。该重写接收类型为SPFeatureReceiverProperties的参数。

从该参数中,您可以进入一个站点:

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"];
  }
}

关于如何迭代该列表,请参考其他答案


-1
正如其他人所说,您不应直接迭代项集合(尤其是在大型集合中)。这是一个替代方案:
// 如果您需要整个集合。否则,在列表上使用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"] 

1
这种方法与迭代项集合相比没有任何好处。问题仍然是您获取了所有列和所有行。更糟糕的是,数据集会变得臃肿。 - Josh

-1

如果您在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


-1

顺便提一下,当使用OPENROWSET时...

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

List = [Name] 对我来说可以代替需要使用list={GUID}。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接