Sitecore 项目反序列化很慢/触发缓存清除

Sitecore item deserialization is slow / triggering cache-clear

问题:当使用 Sitecore.Data.Serialization.Manager 将序列化项目反序列化为 Sitecore 8 时,我的缓存被清除。不应该这样,因为我用选项 DisableEvents = true 调用它,如下所示:

var options = new Sitecore.Data.Serialization.LoadOptions(masterDb);
options.ForceUpdate = true;
options.DisableEvents = true;

using (new Sitecore.SecurityModel.SecurityDisabler())
{
    Sitecore.Data.Serialization.Manager.LoadItem(itemPath, options);
}

尽管如此,缓存正在被清除 - 启用调试后,我得到了这个:

36956 19:32:31 INFO Loading item from path /master/sitecore/templates/SomeFolder/SomeItem.item.

36956 19:32:34 WARN All caches have been cleared. This can decrease performance considerably.

36956 19:32:34 DEBUG All caches have been cleared. Stack trace: at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace() at Sitecore.Caching.CacheManager.ClearAllCaches() at Sitecore.Data.Serialization.Manager.<.cctor>b__1(SerializationFinishedEvent event) at Sitecore.Eventing.EventProvider.RaiseEvent(Object event, Type eventType, EventContext context) at Sitecore.Data.Serialization.Manager.DeserializationFinished(String databaseName)

EDIT/UPDATE

Marek 的回答让我意识到,我说错了。我将原封不动地保留我最初提出的答案,以免造成混淆。但总而言之,使用 选项 DisableEvents 调用 LoadItem 方法 会按预期工作。仅此而已 - 弥补缺少适当的事件被触发 - 触发器 Manager.DeserializationFinished(...) 反过来(至少根据我的默认 Sitecore 8 设置)调用 CacheManager.ClearAllCaches()

我的错误结论是由以下事实引发的,即 CacheManager.ClearAllCaches() 方法是使用 Sitecore 自己的 * EventProvider* 调用的 - 因此,正如 Marek 指出的那样 - 这是一个不幸的巧合/命名冲突。

其实,触发CacheManager.ClearAllCaches()是我想要避免的。所以我想这 "workaround" 不知何故使我的反序列化速度更快(因为它不会为每次执行清除所有缓存)。


原版POST

好吧,所以我去了镇上,最终发现了这个,反汇编 Sitecore.Data.Serialization.Manager.LoadItem(...) 方法(注意:这是 Sitecore 核心内容(带有我的评论)):

public static Item LoadItem(string path, LoadOptions options)
    {
      Assert.ArgumentNotNullOrEmpty(path, "path");
      Assert.ArgumentNotNull((object) options, "options");
      if (!options.DisableEvents) <-------------------------- HERE IS THE BUG
        return Manager.DoLoadItem(path, options);
      Item obj;
      using (new EventDisabler())
        obj = Manager.DoLoadItem(path, options);
      //This next line fires the events - but to get here, DisableEvents must be true.
      Manager.DeserializationFinished(Manager.GetTargetDatabase(path, options));
      return obj;
    }

这看起来像是一个错误。 "If not options.DisableEvents return"。太多了"not"?

解决办法就是设置

options.DisableEvents = false;

将其设置为 false 会禁用在 SerializationFinishedEvent 监听的事件,在本例中是一个处理程序,它会触发 Sitecore.Caching.CacheManager.ClearAllCaches(),正如堆栈跟踪所暗示的那样。尽管看起来应该是相反的。

Frederik,在您的回答中,您粘贴了 LoadItem 方法的反汇编代码,并在您认为存在错误的行中添加了注释:

// QUOTE FROM THE AUTHOR OF THE QUESTION, Frederik Struck-Schøning
public static Item LoadItem(string path, LoadOptions options)
{
    Assert.ArgumentNotNullOrEmpty(path, "path");
    Assert.ArgumentNotNull((object) options, "options");
    if (!options.DisableEvents) <-------------------------- HERE IS THE BUG
      return Manager.DoLoadItem(path, options);
    Item obj;
    using (new EventDisabler())
        obj = Manager.DoLoadItem(path, options);
    //This next line fires the events - but to get here, DisableEvents must be true.
    Manager.DeserializationFinished(Manager.GetTargetDatabase(path, options));
    return obj;
}

然后您解释了您认为此代码不正确的原因。

实际上,这和你写的完全相反

当您反序列化未将 DisableEvents 设置为 false 的项目时,所有缓存都会由 item:saved 和其他事件自动更新。

如果您告诉 Sitecore 禁用所有事件,缓存将永远不会刷新。这就是 Sitecore 在反序列化项目后执行 ClearAllCaches 的原因。不幸的是,在堆栈跟踪中您看到了名称 "event"。所有 Sitecore 事件,如 item:addeditem:createditem:saved 等都不会执行。只有 1 个事件被执行以通知您的当前实例和远程 Sitecore 实例,这个事件是 SerializationFinishedEvent(在其本地和远程版本中)。

所以这是 不是 Sitecore 错误,而是命名问题。这可能会产生误导,但一切都按预期进行。每次保存、更新、重命名等项目时都不会执行一系列事件,而是在 DoLoadItem 方法完成后只有一个通知。