Get value from SPFieldUser with AllowMultipleValues fails only in a Timer Job

3.9k Views Asked by At

This one is weird.

I'm executing this code in a Timer Job in SharePoint 2010 ...

...
// Get the field by it's internal name
SPField field = item.Fields.GetFieldByInternalName(fieldInternalName);

if (field != null)
{
     SPFieldUser userField = (SPFieldUser)field;
     object value = null;

     if (userField.AllowMultipleValues)
     {
          // Bug when getting field value in a timer job? Throws an ArgumentException
          users = new SPFieldUserValueCollection(item.ParentList.ParentWeb, item[userField.Id].ToString());
     }
     else
     {
          // Get the value from the field, no exception
          value = item[userField.Id];
     }
}
...

This code works perfectly when run in a simple ConsoleApplication but when run in the context of a Timer Job in SharePoint 2010 it throws an ArgumentException in the line ...

users = new SPFieldUserValueCollection(item.ParentList.ParentWeb, item[userField.Id].ToString());

I've tried many variations to retreive a value from a SPFieldUser but all fail only when a Timer Job is executing it and the field has AllowMultipleValues property set to TRUE.

I have tried debugging with Reflector and it seems that the exception is being thrown here in SPListItem ...

public object this[Guid fieldId]
{
  get
  {
    SPField fld = this.Fields[fieldId];
    if (fld == null)
    {
      throw new ArgumentException();
    }
    return this.GetValue(fld, -1, false);
}
...

And this here would be the exception stack trace...

System.ArgumentException was caught
Message=Value does not fall within the expected range.
Source=Microsoft.SharePoint
StackTrace:
     at Microsoft.SharePoint.SPFieldMap.GetColumnNumber(String strFieldName, Boolean bThrow)
     at Microsoft.SharePoint.SPListItemCollection.GetColumnNumber(String groupName, Boolean bThrowException)
     at Microsoft.SharePoint.SPListItemCollection.GetRawValue(String fieldname, Int32 iIndex, Boolean bThrow)
     at Microsoft.SharePoint.SPListItem.GetValue(SPField fld, Int32 columnNumber, Boolean bRaw, Boolean bThrowException)
     at Microsoft.SharePoint.SPListItem.get_Item(Guid fieldId)
     at FOCAL.Point.Applications.Audits.AuditUtility.GetPeopleFromField(SPListItem item, String fieldInternalName)

Sighh... any thoughts?

1

There are 1 best solutions below

1
On

This generally means that you have requested too many lookup fields in a single SPQuery which would cause too many self-joins of the true-lookup-table in the content database unless SharePoint Foundation throttled resources. There is a threshold setting that is at 8 lookups per query for ordinary users. Make sure your query only returns the necessary lookup or person/group fields. If you can't decrease the usage, then consider altering the threshold setting.