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:added
、item:created
、item:saved
等都不会执行。只有 1 个事件被执行以通知您的当前实例和远程 Sitecore 实例,这个事件是 SerializationFinishedEvent
(在其本地和远程版本中)。
所以这是 不是 Sitecore 错误,而是命名问题。这可能会产生误导,但一切都按预期进行。每次保存、更新、重命名等项目时都不会执行一系列事件,而是在 DoLoadItem
方法完成后只有一个通知。
问题:当使用 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:added
、item:created
、item:saved
等都不会执行。只有 1 个事件被执行以通知您的当前实例和远程 Sitecore 实例,这个事件是 SerializationFinishedEvent
(在其本地和远程版本中)。
所以这是 不是 Sitecore 错误,而是命名问题。这可能会产生误导,但一切都按预期进行。每次保存、更新、重命名等项目时都不会执行一系列事件,而是在 DoLoadItem
方法完成后只有一个通知。