Доступ к информации из CommonPart очень медленный? - PullRequest
0 голосов
/ 04 апреля 2019

Я новичок в 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 голосов
/ 19 апреля 2019

При доступе к свойству Owner из вашего Select ленивый загрузчик в CommonPartHandler просит менеджера контента загрузить элемент контента пользователя: _contentManager.Get<IUser>(part.Record.OwnerId). Это происходит один раз для каждого элемента контента в результате вашего запроса, поэтому в результате вы получите n + 1, где n = 1200 в соответствии с вашим вопросом.

Есть как минимум два способа избежать этого:

  1. Вы можете использовать HQL и создать запрос, который даст вам все необходимое за 1 операцию.
  2. Вы можете сделать первый запрос менеджера контента, чтобы получить набор идентификаторов владельца, а затем сделайте второй запрос менеджера контента для этих идентификаторов и получите все, что вам нужно, всего 2 запроса вместо 1201.
...