For a Sitecore 8.2 solution I have a save event handler that populates a field on an item of several different templates based upon items that refer to its child items via the Link Database. That logic works correctly but I am facing two different issues depending on the environment.
- In my local and test server environment, everything works as expected, however, in order to see the new values on the item I have to save twice. Stepping through the code shows that the field is populated the first time but is then cleared after the EndEdit() line is run. When I save again the value is preserved after the EndEdit().
After looking at this more I found that if I save once and then clear all the caches and come back to the item the values show up, indicating that it is a caching issue. Occasionally it will show the values on the 1st save but this only happens maybe 30% of the time. However as shown in the code, cacheManager is set to false when I actually edit the item, but it does not prevent the issue.
I'm looking for a solution so it always shows the updated value to the user on item save. Is there a way to clear a specific cache or even this specific item in that cache or is there a different way to handle this?
- On a dev server environment I notice different behavior. I can save multiple times and clear the cache and the field is not populated. It is not until I change the value on a different field in the content editor and save that it updates. I often have to update that different field and save twice for this to actually update, or I need to edit the other field once and then clear the cache for it show the updated field.
I am not sure why this behavior is different as the environments are fairly similar, with the biggest difference being that the dev server is a standalone instance (no CDs) just like my local machine while the test environment scalable (CM and CD servers).
Update 1
I have updated the code below at the end after CacheManager.Enabled = true; It now includes a clearing of the master database items cache. Doing this appears to allow the item to display the updated values immediately on local and test environment but not the dev dev environment. However, this clears the entire item cache. I would prefer to only clear the item being updated in the cache instead but do not see any methods available with ICacheInfo to do this.
public class ProductModelAccComputedSaveHandler
{
protected void OnItemSaved(object sender, EventArgs args)
{
if (args == null) return;
Item savedItem = Event.ExtractParameter(args, 0) as Item;
if (savedItem == null || savedItem.Database.Name.ToLower() != "master") return;
// List of product model template IDs to ensure this logic only applies to models
List<ID> productTemplateIds = new List<ID>
{
new ID("{2E8728B0-22C0-4805-A87D-22FFEEEB0537}"),
new ID("{B9D9508E-24F7-4EDC-94BD-6CF494CDF12C}"),
new ID("{A5CFE2B3-3EB8-4B7C-9BC9-0126EA3417E6}"),
new ID("{9417E6E9-8A84-4EE5-B5B2-A89626C579FA}"),
};
if (productTemplateIds.Contains(savedItem.TemplateID))
{
List<string> accessoryIDS = new List<string>();
foreach (Sitecore.Data.Items.Item modelOption in savedItem.Children)
{
var modelOptionReferrers = ExtensionMethods.SitecoreItemExtensions.GetReferrers(modelOption);
var modelOptionRefAccessories = Array.FindAll(modelOptionReferrers, c => c != null && c.TemplateID == new ID("{1385E0E6-3DA1-4636-A69C-2A5A8B299155}")).ToList();
foreach (var accessory in modelOptionRefAccessories)
{
accessoryIDS.Add(accessory.ID.ToString());
}
}
accessoryIDS = accessoryIDS.Distinct().ToList();
Sitecore.Data.Fields.MultilistField assignedAccessories = savedItem.Fields["Accessories Assigned to This Product"];
if (accessoryIDS != null && accessoryIDS.Count != 0)
{
CacheManager.Enabled = false;
using (new Sitecore.SecurityModel.SecurityDisabler())
{
using (new EventDisabler())
{
savedItem.Editing.BeginEdit();
try
{
// clear field values so this event handler does not just keep adding and adding values
assignedAccessories.Value = string.Empty;
foreach (var accessory in accessoryIDS)
{
assignedAccessories.Add(accessory);
}
savedItem.Editing.EndEdit();
}
catch (Exception ex)
{
savedItem.Editing.CancelEdit();
Log.Error("Error updating computed field:" + ex, this);
}
CacheManager.Enabled = true;
var masterCaches = CacheManager.GetAllCaches();
var masterItemCache = masterCaches.SingleOrDefault(c => c.Name == "master[items]");
masterItemCache.Clear();
}
}
}
}
}
}
item:saved
toitem:saving
?EventDisabler())
from your method and remove clearing caches. EventDisabler pretty much tells Sitecore to only change data in database but ignore refreshing of all the caches