Лишние запросы значений свойств объекта используемого в качестве датасоурса
Обнаружил, что запрашиваются свойства, которые не выбраны для отчета (в диалоге Выбрать данные для отчёта ...). Это снижает производительность. Как сделать чтобы запрашивались только те свойства, которые нужны для построения отчёта ?
Комментарии
1) срабатывает точка останова, поставленная в код get, после вызова методов report.Load (или report.RegisterData)
2) по трассировке стека видно, что инициаторами запросов являются методы report.Load (или report.RegisterData)
каждое свойство запрашивается 1 раз при
report.RegisterData(...);
и 2 раза при
report.Show();
Я не знаю зачем так делается, но считаю, что должно быть достаточно только одного получения значения свойства;
Это существенно повысит производительность в случае если получение значения свойства связано с тяжелыми операциями, типа запроса в БД (как в моем случае).
Если многократное получение значения свойства требуется для каких-то механизмов, предлагаю добавить возможность отключения этих механизмов.
Значения свойств возвращающих ссылочные (непростые) типы тоже запрашиваются даже, если они не включены в данные для отчета. Это происходит 1 раз при report.RegisterData(...);
Если свойство есть в выбранных данных, но не используется в отчете, то его значение не должно запрашиваться.
[MyObject.ComplexProperty.SimpleProperty] - будет каждый раз браться значение св-ва ComplexProperty, затем - SimpleProperty.
По поводу проверки на новые или старые поля: для этого наверняка используется reflection, но тогда непонятно зачем значения свойств.
Если разработчик точно знает, что набор полей в классе не изменится, то было бы полезно вообще отключить проверку на старые и новые поля.
Я наверное не всё понимаю, но пожелание остается в силе.
Это необходимо, т.к. тип свойства зачастую не дает всей нужной информации. Например, если это ArrayList.
По поводу этой проверки я уже написал, что ситуация улучшится в следующем билде (завтра).
Можно построить DataSet на основе объектного датасоурса, а потом обращаться только к этому DataSet'у.
Понятно,
предлагаю создать утилитный метод, который преобразует List<EntityType> в DataSet в соответствии с датасурсом отчёта. И разработчик уже сам сможет решать, что подпихивать List<EntityType> или DataSet.
Бывают отчёты
детализированные: в них много данных, но они простые (быстро вычисляются) - здесь лучше List<EntityType>
а бывают,
агрегатные - в них наоборот мало данных, но они сложные (агрегируют много простых, долго вычисляются) - здесь лучше DataSet.
У меня агрегатный отчет. Я сам могу конечно DataSet сделать, но лучше чтобы это report сделал, так как он знает какие свойства нужны для отчёта.
Работать будет быстрей так как при создании DataSet значение свойства объекта будет запрашиваться только один раз. DataSet в этом случае выступает в роли кэша. Это выгодно когда для получения значения свойства требуется запрос к БД или другая дорогая операция. В принципе вместо DataSet можно разработать какую-нибудь более легковесную специализированную структуру данных для кэширования значений свойств.
Сделайте класс с нужным набором св-в и заполните экземпляр класса нужными данными, самым для Вас оптимальным способом. И его уже регистрируйте в отчете.
При построении отчета был сделан 1-й запрос значения свойства. Далее данные в БД меняются.
2-й запрос значения свойства возвращает уже другое другое значение.
Что тогда происходит?
Тоже самое, если значение свойства меняется в другом потоке или для получения значения свойства требуется пользовательский ввод.
В качестве этого экземпляра класса может выступать DataSet. Я могу это сделать, но мне кажется report с этим может лучше справиться, так как знает какие данные нужны для отчёта.
Давайте лучше рассуждать, используя конкретный пример (кусок кода). Я может чего-то не понимаю, но, мне кажется, в существующем механизме оптимизировать нечего.
Как определяется актуальность значения свойства?
Пример кода:
потеряли 4 секунды при вызовах eportObject.ReportField, чего можно было избежать если закэшировать значение reportObject.ReportField при первом запросе
еще потеряли 2 секунды на ненужный запрос reportObject.ReferenceTypeField
я бы хотел так:
Вы заполняете этот класс данными из своего объекта:
Я думаю, я не единственный человек, который имеет сущности с "тяжелыми" свойствами и хочет использовать эти сущности в качестве источников данных для отчетов. Особенно это актуально для ORM сущностей с lazy load свойствами.
Другой вариант, чтобы FR всё-таки кэшировал значения свойств и не запрашивал их значения по несколько раз.
В новом билде, запрашивать свойства по несколько раз FR будет только в том случае, если они несколько раз используются в отчете. Например, св-во ReportField печатается дважды в разных объектах "Текст".
И ещё:
В отчете соответственно есть родительский (для ReportObject) и дочерний банд (ReportObject.ReportChildObjectList) данных;
Хотелось бы чтобы ReportObject.ReportChildObjectList запрашивалось 1 раз.
ReportChildObjectList сейчас запрашивается лишний раз при регистрации данных. Этот лишний запрос я уберу с помощью св-ва UsePropValuesToDiscoverBO в следующем билде. Его надо установить в false перед регистрацией данных:
Config.ReportSettings.UsePropValuesToDiscoverBO = false;
report.RegisterData(...);
при запуске отчета лишних запросов не будет (по одному на каждую строку master). Также у бэнда master надо будет установить св-во PrintIfDetailEmpty = true.