Наиболее оптимальный и рациональный алгоритм работы с отчётами

Обсуждение Stimulsoft Reports.NET
Ответить
Аватара пользователя
Андрей Сорокин
Сообщения: 107
Зарегистрирован: 02 июл 2009, 11:31
Откуда: Bryansk, Russia
Контактная информация:

Наиболее оптимальный и рациональный алгоритм работы с отчётами

Сообщение Андрей Сорокин »

Добрый день!

Прочитав переписку http://forum.stimulsoft.com/Default.aspx?g=posts&t=142 у меня возникли сомнения по поводу корректности и оптимальности используемого мною алгоритма при работе с отчётами.
Я делаю так:
1. Сохраняю каждый отчёт из дизайнера в своём DLL-файле, которые затем поставляются в дистрибутиве конечным пользователям.
2. Использую следующий класс для загрузки, инициализации переменных и параметров, отображения и печати отчётов, инициализировав его в начале программы: Report.Init("bla-bla-bla");

Код: Выделить всё

using System;
using System.Windows.Forms;
using System.Collections;
using System.Data;
using Stimulsoft.Report;
using Stimulsoft.Report.Dictionary;

namespace ReportStimul
{
    public static class Report
    {
        private static string ReportFilesPath;
        private static string ConnectionString;

        public static object RecordSet;
        public static Hashtable Fields;

        public static void Init(string ConnectionString)
        {
            Report.ConnectionString = ConnectionString;
            ReportFilesPath = System.IO.Directory.GetCurrentDirectory();
            StiConfig.LoadLocalization(ReportFilesPath + @"\ru.xml");
            Fields = new Hashtable();
        }

        public static void Generate(string ReportName, bool ShowPreview, bool LoadOnce)
        {
            try
            {
                using (StiReport report = StiReport.GetReportFromAssembly(ReportFilesPath + ReportName + ".dll", LoadOnce))
                {
                    if (RecordSet != null)
                    {
                        if (RecordSet is DataSet) report.RegData(RecordSet as DataSet);
                        else if (RecordSet is DataTable) report.RegData(RecordSet as DataTable);
                        else if (RecordSet is DataView) report.RegData(RecordSet as DataView);
                    }
                    else
                    {
                        report.Dictionary.Databases.Clear();
                        report.Dictionary.Databases.Add(new StiSqlDatabase("Connection", ConnectionString));
                    }
                    if (Fields.Count > 0)
                    {
                        foreach (DictionaryEntry de in Fields)
                        {
                            if (de.Value != null) report[de.Key.ToString()] = de.Value;
                        }
                    }
                    if (ShowPreview)
                    {
                        report.Show(true);
                    }
                    else
                    {
                        report.Print(false);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex);
            }
            finally
            {
                RecordSet = null;
                Fields.Clear();
            }
        }
    }
}
При последовательных генерациях отчётов наблюдаются незначительные увеличения используемой памяти.
Всё ли корректно в моём коде?
Может есть более быстрые и рациональные способы работы с отчётами?
По поводу параметра LoadOnce: когда лучше использовать true, а когда false? Я делаю так: если пользователь точно будет использовать какой-либо отчёт передаю true, если пользователь может не использовать какой-либо отчёт в работе передаю false.

Генерить классы отчётов и компилить их вместе с приложениями считаю нецелесообразным, т.к. отчётов довольно много и при загрузке приложения все отчёты (весь код приложения) будут загружаться в память, а использоваться в работе в текущем сеансе может всего лишь какой-нибудь один отчёт.
Компилировать клиентом *.mrt файлы при первом запуске отчёта также считаю нецелесообразным, т.к. процесс отнимает некоторое время, думаю предпочтительнее использовать готовые DLL.

Заранее спасибо!
Jan
Сообщения: 495
Зарегистрирован: 19 фев 2009, 11:14

Наиболее оптимальный и рациональный алгоритм работы с отчётами

Сообщение Jan »

Здравствуйте,

Основной недостаток Вашей схемы работы это то, что при изменении версии генератора отчетов придется все отчеты пересохранить. Причем сделать это придется вручную. Самый удачный способ это способ описанный в топик из переписки. Т.е. пользователю поставляем mrt файлы. При запуске отчета проверяем если скомпилированная версия, с какой версией генератора отчетов она скомпилирована и если сборка есть и ее версия соотвествует версии генератора отчетов, то грузим отчет оттуда. Если сборки нет, то произведоим ее компиляцию (это делается не каждый раз при запуске программы, а один раз). Каждый отчет в таком случае компилируется только один раз при первом запуске (или если его версия к примеру изменилась). Методика описанная в приведенной переписке позволяет легко проверить это. Также можно сделать процедуру - "Скомпилировать все отчеты", т.е. выполнить сразу компиляцию всех отчетов за один проход при любом изменении отчетов.

По поводу GetReportFromAssembly и LoadOnce флага. Смысл флага такой. Если флаг равен true, то сборка отчета загружается из файла напрямую. При этом файл сборки блокируется до завершения работы приложения. Если еще раз попытаться загрузить эту же сборку, то будет использована уже загруженная копия. Если флаг равен false, то файл сборки будет загружен через Stream. Stream в данном случае работает как барьер между сборкой и файлом сборки. Т.е. файл останется не залоченым, но и сборка будет загружена столько раз, сколько будет вызван этот метод (в реальности .Net Framework все равно скопирует сборку на диск в файл, только сделает это прозрачно).

Спасибо.
Ответить