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…)
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 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 Oskar Austegard, at Monday, July 19, 2010 3:43:00 PM
Post a Comment
<< Home