从CommonPart访问信息非常慢?

时间:2019-04-04 03:21:15

标签: c# orchardcms

我是Orchard的新手,这必须涉及基础数据的存储方式。

CommonPart的加入似乎足够快,就像这样:

var items = _contentManager.Query<MyUserPart, MyUserPartRecord>("someTypeName")
                           .ForVersion(VersionOptions.Published)
                           .Join<CommonPartRecord>().List().ToList();

运行速度非常快。但是,每当我尝试访问CommonPart中的某个字段时,它的运行都会非常缓慢,如下所示:

var items = _contentManager.Query<MyUserPart, MyUserPartRecord>("someTypeName")
                           .ForVersion(VersionOptions.Published)
                           .Join<CommonPartRecord>().List()
                           //access some field from commonpart
                           .Select(e => new {                               
                               User = e.As<CommonPart>().Owner.UserName
                            }).ToList();

总数据约为1200个项目,所需的时间约为5 seconds,它不会像这样缓慢。对于在后台运行的简单SQL查询,该过程大约需要0.5秒甚至更少的时间。

我曾尝试调查Orchard的源代码,但没有发现可能是问题所在。在IContent的访问点,所有内容似乎都进入了黑箱。我希望这里有人可以给我一些建议,以诊断和解决这个难题。谢谢!

更新

我尝试调试一下,发现在DefaultContentManager中遇到了以下方法:

ContentItem New(string contentType) { ... }

这真的很有趣,查询只是在查询数据而无需修改,插入和更新任何内容。但是被击中的方法表明这里有些问题。

更新

在@Bertrand Le Roy的评论中,我尝试使用QueryHint编写以下代码,但看起来它并没有改变任何东西:

var items = _contentManager.Query<MyUserPart, MyUserPartRecord>("someTypeName")
                           .ForVersion(VersionOptions.Published)
                           .Join<CommonPartRecord>()
                           .WithQueryHints(new QueryHints().ExpandParts<CommonPart>())
                           .List()
                           //access some field from commonpart
                           .Select(e => new {                               
                               User = e.As<CommonPart>().Owner.UserName
                            }).ToList();

和这个(没有.Join

var items = _contentManager.Query<MyUserPart, MyUserPartRecord>("someTypeName")
                           .ForVersion(VersionOptions.Published)
                           .WithQueryHints(new QueryHints().ExpandParts<CommonPart>())
                           .List()
                           //access some field from commonpart
                           .Select(e => new {                               
                               User = e.As<CommonPart>().Owner.UserName
                            }).ToList();

1 个答案:

答案 0 :(得分:0)

Owner访问Select属性会使CommonPartHandler中的惰性加载器要求内容管理器加载用户内容项:_contentManager.Get<IUser>(part.Record.OwnerId)。对于您的查询,每个内容项都会发生一次,因此会根据您的问题导致选择n + 1,其中n = 1200

至少有两种方法可以避免这种情况:

  1. 您可以使用HQL并编写查询,使您只需一次操作即可获得所需的一切。
  2. 您可以进行第一个内容管理器查询,以获取所有者ID集合,然后 对这些ID进行第二次内容管理器查询,并通过2个查询(而不是1201个)来获得所需的一切。