在代码中查询 Sitecore 数据库有时不会返回任何内容



我们使用的是 Sitecore 6.5 r111230。

我们有一个高度定制的 Sitecore 解决方案(基本上由第三方设计机构完成交付给我们;它基本上没有文档记录,我们不再与他们有任何业务安排(,它广泛使用了通过 C# 代码查找的 Sitecore 项目。最终,多层抽象调用Sitecore.Data.Database.GetItem(path)其中path是正常的 sitecore 查询。

间歇性地,此调用针对常量路径返回 null,引用我知道存在且未更改的项目。我已经通过逐步浏览Visual Studio中的代码看到了这种情况。

我们认为这与索引有关,因为当索引(包含被视为丢失的项目(被重建时,sitecore 日志会定期填满 FileNotFoundException 或 UnauthorisedAccessException。但是,在查看了文档后,似乎很明显,您必须显式查询Index实例才能从索引中检索项目,并且没有"魔术"可以在索引其内容时将调用重定向到Database。因此,我现在已经排除了这是问题的原因。

是什么导致了这种非常奇怪的行为?

编辑#1:

在我发布问题后不久,我突然想到了一个想法。该解决方案包括一个自定义索引重新生成处理程序,该处理程序处理发布事件结束,并在其中一个自定义索引上启动索引重新生成作业。如果此作业由于(例如(运行它的帐户对存储索引的文件夹没有适当的权限而崩溃,这是否会中止触发它的发布?这一观点得到了以下观察的支持:由"创作"应用程序(从master运行(运行的查询似乎工作正常,而"交付"应用程序(web(失败。这对我来说意味着发布失败 - 尽管它们都是在发布之前应该已经存在的项目。如果可能,我如何验证这是原因?

编辑#2:

更奇怪的是,在同一站点上,据我所知,从同一台机器提供服务(尽管有两个负载平衡(浏览同一页面的不同用户会得到不同的结果,其中返回的项目是恒定的,不依赖于用户。我感到无比困惑,现在感到困惑。

编辑#3:

我可能更接近弄清楚这里发生了什么。间歇性丢失的项目位于具有类似文件夹的模板的项目层次结构中,并且可通过路径进行访问。在过去的某个时候,原始项目被重命名为"备份",并创建了一个具有原始名称的新项目,并将项目复制到其中以保留层次结构,然后再进行一些增量更改。

我认为问题与预取缓存有关,预取缓存有一个由项目(现在重命名的项目(的 id 标识的条目。我假设当应用程序启动时,预取缓存会加载旧项目的子项,解释"丢失"项目(现在存在但备份时不在旧文件夹中的项目(或"错误"的项目(存在但已更改的项目(。当从 CM 发布任何内容或保存项目时,将使用正确的数据重建更高级别的缓存,问题就会消失,因此看起来"间歇性"。

对于 Sitecore 专家:如果配置错误,预回迁缓存能否执行此操作?

以下是您可以查看的一些内容:

  1. 某些代码正在切换上下文数据库。如果数据在 Web 中,数据在 Master 中,是否有任何代码将上下文数据库切换到"核心"?然后,查询将找不到该项,因为它在错误的数据库中查找。
  2. 某些代码正在切换语言。如果数据在那里,但没有返回,则可能是没有该语言的版本。是否有任何代码以编程方式切换上下文语言?
  3. 数据缓存已损坏 我还没有看到索引重建或发布导致以前存在的项目在 GetItem 调用时无法返回,但我肯定看到缓存清除问题导致 Sitecore 认为某个项目不存在,因为它清除了数据,但随后没有再次将其重新加载到缓存中。如果执行完全缓存刷新(使用 admin\Cache.aspx(,它会立即解决问题吗?

需要排除的几件事:

  • 如果 API 调用与您描述的完全一致;则问题与 Sitecore 查询无关。Database.GetItem(( 不使用 Sitecore Query
  • 它也不能是版本控制或语言切换。在这两种情况下,您都会获得项目的非空结果,即使上下文语言没有版本
  • 它也不能与索引相关,因为 Database.GetItem 不利用索引来检索结果
  • 它不能与权限相关,如果 - 正如您声称的那样 - 代码位于 SecurityDisabler(( 中

那么我们还剩下什么呢? 老实说,我认为您可能在某处有一个错误的假设 - GetItem(( 调用返回 null,因此可能具有其他一些副作用。您可能会看到副作用,并得出结论,它一定是返回 null 的 GetItem 调用。我相信情况确实如此,因为您说您在浏览同一个框(服务器(的两个不同浏览器上获得了不同的结果。在我看来,这个问题更有可能的候选者是:

  • 您的可伸缩性设置.config 未启用。这可能会在多服务器设置中给您带来问题。但是,它不会解释您描述的结果,其中两个不同的浏览器在同一服务器上查看同一页面会产生不同的结果。但是,它可以解释为什么 .GetItem(( 将在一台服务器上返回结果,而不是在另一台服务器上返回结果
  • 缓存。更具体地说,在相关控件/组件上配置的每用户缓存。这不会使您的.GetItem(( 返回 null,但它可能会让你误入歧途,让你相信它有。我需要更多地了解您的解决方案才能得出任何结论。每用户缓存是 Sitecore 解决方案中为数不多的可以解释同一框上两个单独浏览会话的不同行为的功能之一
  • 上下文数据库不是您所期望的。通常,仅当您执行位于站点根目录之外的定制.aspx页面时,才会发生这种情况。你写的任何内容似乎都没有表明情况如此。

希望这有所帮助。将有助于更多地了解导致您怀疑的症状。GetItem,或有关解决方案的更多信息。

我将从验证服务器上的数据库配置引用开始。- 连接字符串指向相同的数据库- 数据库定义与正确的连接字符串相关联- 网站定义使用相同的数据库

添加到Jay和Maras的评论中,请检查您是否有任何带有破折号的项目'-'或以0开头。如果是这样,则需要添加逻辑以用'#'符号包装它们。像这样:/sitecore/content/home/#folder-name#/year/#0001#.

最新更新