Wednesday, October 14, 2009

Get SPListItem from SPList

Working with SPList was found that upon receipt of a list item on Guid of SPListItemCollection.this [Guid] took a lot of time on a large collection. 
It looked like this:



  1. var uniqId = new Guid(/* get GUID somehow */);
  2. SPList list = /* get list somehow */;
  3. SPListItem anItem = list.Items[uniqId];
* This source code was highlighted with Source Code Highlighter.

But it turns out, there is another way to get a list item SPList.GetItemByUniqueId(Guid uniqueId). Using this method does not arise for the delay in large collections. To determine the differences we use the reflector, and see how to implement a method to obtain an element in the collection for SPListItemCollection in Microsoft.SharePoint.dll. That's what we see in SPListItemCollection.this[Guid]:



  1. public SPListItem this[Guid uniqueId]
  2. {
  3.  get 
  4.  { 
  5.   this.EnsureListItemsData(); 
  6.   this.EnsureFieldMap(); 
  7.   int iIndex = 0; 
  8.   int columnNumber = this.m_mapFields.GetColumnNumber("UniqueId"); 
  9.   string str2 = uniqueId.ToString("B").ToLower(); 
  10.   while (true
  11.   {  
  12.    if (iIndex >= this.m_iRowCount)  
  13.    {  
  14.     throw new ArgumentException();  
  15.    }  
  16.    string str = ((string) this.m_arrItemsData[columnNumber, iIndex]).ToLower();  
  17.    int num3 = SPUtility.StsBinaryCompareIndexOf(str, ";#");  
  18.    if ((num3 > 0) && (str.Substring(num3 + 2) == str2))  
  19.    {  
  20.     this.EnsureListItemIsValid(iIndex);  
  21.     if (this.m_iColection == null)  
  22.     {   
  23.      return new SPListItem(this, iIndex);  
  24.     }  
  25.     return this.m_iColection.ItemFactory(iIndex);  
  26.    }  
  27.    iIndex++; 
  28.   } 
  29.  }
  30. }
* This source code was highlighted with Source Code Highlighter.

As we can see the contents of the entire collection moves an element by element, each element is calculated with a given match GUID'a. More collection - the longer work. 

And now look at the implementation of the method GetItemByUniqueId for SPList:



  1. public SPListItem GetItemByUniqueId(Guid uniqueId)
  2. {
  3.  SPQuery query = new SPQuery();
  4.  query.Query = "<Where><Eq><FieldRef Name=\"UniqueId\"></FieldRef><Value Type=\"Guid\">" + uniqueId.ToString("B") + "</Value></Eq></Where>";
  5.  query.ViewAttributes = "Scope=\"RecursiveAll\" ModerationType=\"Moderator\"";
  6.  query.MeetingInstanceId = -2;
  7.  query.QueryOpt = SPQuery.SPQueryOpt.None | SPQuery.SPQueryOpt.UniqueId;
  8.  SPListItemCollection items = this.GetItems(query);
  9.  
  10.  if (items.Count != 0)
  11.  {
  12.   return items[0];
  13.  }
  14.  
  15.  while (!(this.ID == this.Lists.Web.UserInfoListId))
  16.  {
  17.   throw new ArgumentException();
  18.  }
  19.  throw new ArgumentException(SPResource.GetString("CannotFindUser", new object[0]));
  20. }
* This source code was highlighted with Source Code Highlighter.

Here, using SPQuery, we obtain directly the very record without sorting the collection. 
Conclusion: The use of large lists SPList.Items[Guid] - long, unproductive. Better to use SPList.getItemByUniqueId(Guid);

No comments:

Post a Comment