📜 ⬆️ ⬇️

Get the SPListItem from the SPList. Very fast and very slow

When profiling a web part for SharePoint, I was surprised to find a bottleneck in SPListItemCollection.this [Guid] ... Getting a list item by Guid, in fact, the primary key, took a lot of time on a large collection.
It happened like this

var uniqId = new Guid ( /* get GUID somehow */ );
SPList list = /* get list somehow */

SPListItem anItem = list.Items[uniqId];


* This source code was highlighted with Source Code Highlighter .
How are there any methods to get an item from the list?
There is SPList.GetItemByUniqueId (Guid uniqueId) - there is no such delay when using. Why?

We use a reflector, and re-engineer the shapaponit ...
')
This is what we see in SPListItemCollection.this [Guid]:

public SPListItem this [ Guid uniqueId]
{
get
{
this .EnsureListItemsData();
this .EnsureFieldMap();
int iIndex = 0;
int columnNumber = this .m_mapFields.GetColumnNumber( "UniqueId" );
string str2 = uniqueId.ToString( "B" ).ToLower();
while ( true )
{
if (iIndex >= this .m_iRowCount)
{
throw new ArgumentException();
}
string str = (( string ) this .m_arrItemsData[columnNumber, iIndex]).ToLower();
int num3 = SPUtility.StsBinaryCompareIndexOf(str, ";#" );
if ((num3 > 0) && (str.Substring(num3 + 2) == str2))
{
this .EnsureListItemIsValid(iIndex);
if ( this .m_iColection == null )
{
return new SPListItem( this , iIndex);
}
return this .m_iColection.ItemFactory(iIndex);
}
iIndex++;
}
}
}


* This source code was highlighted with Source Code Highlighter .

The content of the entire collection is scrolled item by element, for each element a matching GUID is calculated with the given one. The larger the collection - the longer we work.

And now GetItemByUniqueId:
public SPListItem GetItemByUniqueId( Guid uniqueId)
{
SPQuery query = new SPQuery();
query.Query = "<Where><Eq><FieldRef Name=\"UniqueId\"></FieldRef><Value Type=\"Guid\">" + uniqueId.ToString( "B" ) + "</Value></Eq></Where>" ;
query.ViewAttributes = "Scope=\"RecursiveAll\" ModerationType=\"Moderator\"" ;
query.MeetingInstanceId = -2;
query.QueryOpt = SPQuery.SPQueryOpt.None | SPQuery.SPQueryOpt.UniqueId;
SPListItemCollection items = this .GetItems(query);
if (items.Count != 0)
{
return items[0];
}
while (!( this .ID == this .Lists.Web.UserInfoListId))
{
throw new ArgumentException();
}
throw new ArgumentException(SPResource.GetString( "CannotFindUser" , new object [0]));
}


* This source code was highlighted with Source Code Highlighter .

Here, using SPQuery, we get directly the record itself without iterating over the collection.

Conclusion: on large lists, using SPList.Items [Guid] is long, unproductive. Better to choose SPList.getItemByUniqueId (Guid);

UPD : Thanks vladem - a useful link to a thematic KB - http://msdn.microsoft.com/en-us/library/bb687949.aspx

Source: https://habr.com/ru/post/71906/


All Articles