EditIs it dirty?
This hack demonstrates figuring out if an SPListItem is dirty, when compared to the version currently held in the database... I used this code to determine if I needed to save the ListItem or not (to avoid change notification work flows being run unnecessarily)
EditHow it works
I checks the title and attachments, and then proceeds to check all non-base-type fields, I do string comparisons (ugly code!) - but it satisfied the client requirements at the time.
EditThe Code
public static bool IsItemDirty(SPListItem item, SPListItem existing)
{
if (object.Equals(item, existing)) throw new Exception("existing and current must not be the same instance");
if (existing.Title != item.Title)
{
return true;
}
if (existing.Attachments.Count == item.Attachments.Count)
{
for (int i = 0; i < existing.Attachments.Count; i++)
{
if (existing.Attachments[i] != item.Attachments[i])
{
return true;
}
}
}
else
{
return true;
}
foreach (SPField field in item.Fields)
{
if (!field.FromBaseType)
{
try
{
string fieldName = field.InternalName;
string x = string.Format("{0}", existing[fieldName]).Trim();
string y = string.Format("{0}", item[fieldName]).Trim();
SPFieldMultiLineText textField = field as SPFieldMultiLineText;
if ((textField != null) && textField.AppendOnly && string.IsNullOrEmpty(y))
{
continue;
}
switch (field.Type)
{
case SPFieldType.User:
case SPFieldType.Lookup:
x = ExtractDigits(x);
y = ExtractDigits(y);
break;
default:
break;
}
if (!string.Equals(x, y, StringComparison.InvariantCulture))
{
return true;
}
}
catch (Exception ex)
{
if (logDetails) item[FieldNames.Task.Notes] = ex.ToString();
return true;
}
}
}
return false;
}
public static string ExtractDigits(string text)
{
string accumulated = "";
foreach (char c in text)
{
if (char.IsDigit(c)) accumulated += c;
else break;
}
return accumulated;
}
public static bool IsItemDirty(SPListItem item)
{
try
{
SPListItem existing = item.ListItems.GetItemById(item.ID);
return IsItemDirty(item, existing);
}
catch (Exception)
{
return true;
}
}