mo.notono.us

Monday, March 30, 2009

Beware of SPList.Items.Add()

What could possibly be wrong with this statement?

SPListItem myItem = myList.Items.Add();

This is what’s wrong with it – this is the innards of SPList.Items:

public virtual SPListItemCollection Items
{
    get
    {
        SPQuery query = new SPQuery();
        query.ViewAttributes = "Scope=\"Recursive\"";
        return this.GetItems(query);
    }
}

That’s right, the entire collection, every single item, item is returned and then Add() is applied to the final SPListItemCollection instance, which results in an internal SPListItem constructor call:

public SPListItem Add(string folderUrl, 
    SPFileSystemObjectType underlyingObjectType, string leafName)
{
  return new SPListItem(this, folderUrl, underlyingObjectType, leafName);
}
internal SPListItem(SPListItemCollection items, string folderUrl, SPFileSystemObjectType underlyingObjectType, string leafName)
{
    this.m_ItemGuid = Guid.Empty;
    this.m_fsoType = SPFileSystemObjectType.Invalid;
    if (underlyingObjectType != SPFileSystemObjectType.File)
    {
        while (underlyingObjectType != SPFileSystemObjectType.Folder)
        {
            throw new ArgumentOutOfRangeException("underlyingObjectType");
        }
    }
    this.m_Items = items;
    this.m_uiItemsUpdateVersion = items.UpdateVersion;
    this.m_iIndex = -1;
    this.m_strNewFolderName = folderUrl;
    this.m_fsoType = underlyingObjectType;
    this.m_strNewBaseName = leafName;
    this.m_bNewItem = true;
}

So what should be used instead?  Rob Garrett suggests creating a new empty SPListItemCollection and adding to it, below is his method converted to an Extension method (and renamed to be more easily found):

public static SPListItem AddItemOptimized(this SPList list)
{
  const string EmptyQuery = "0";
  SPQuery q = new SPQuery {Query = EmptyQuery};
  return list.GetItems(q).Add();
}

 

(and no, neither Rob nor I have instrumented the difference between these two methods, but Reflector doesn’t lie…)

Labels: , , , , ,

2 Comments:

  • Great find! I think your optimized method could be pretty useful to add items to a big list.

    I hope they fix this in Sharepoint 2010.

    By Blogger Prashant, at Tuesday, September 22, 2009 2:01:00 AM  

  • SharePoint 2010 addresses this through adding an AddItem method for the SPList class. Internally it uses the static SPQuery.TrivialQuery (essentially an empty query*) to add the item to an empty ListItem collection, achieving the same effect as AddItemOptimized():

    *TrivialQuery code:

    internal static SPQuery TrivialQuery
    {
    get
    {
    SPQuery query = new SPQuery();
    query.Query = "<Where><Eq><FieldRef Name=\"ID\"/><Value Type=\"Integer\">-1</Value></Eq></Where>";
    query.ViewFields = "<FieldRef Name=\"ID\"/>";
    return query;
    }
    }

    By Blogger Oskar Austegard, at Monday, July 19, 2010 3:43:00 PM  

Post a Comment

<< Home