internal ReportResultCacheKey(ReportSettings reportSettings, IQueryRunnerCacheKey reportQueryKey, IQueryRunnerCacheKey rollupQueryKey)
        {
            if (reportSettings == null)
            {
                throw new ArgumentNullException("reportSettings");
            }
            if (reportQueryKey == null)
            {
                throw new ArgumentNullException("reportQueryKey");
            }
            // rollupQueryKey may be null

            ReportQueryKey = reportQueryKey;
            RollupQueryKey = rollupQueryKey;
            Bools          = PackBools(reportSettings);
            ColumnCount    = reportSettings.ColumnCount;

            // The following reportSettings do not need to be covered in this key:
            // - SupportPaging, PageSize, InitialRow (denied)
            // - ReportParameters, Timezone, ReportOnType, QuickSearch, FilteredEntityIdentifiers, RelatedEntityFilters
            // - UseStructuredQueryCache, RefreshCachedResult, RefreshCachedSql, RefreshCachedStructuredQuery

            _hashCode = GenerateHashCode();
        }
        /// <summary>
        /// Runs the report.
        /// </summary>
        /// <param name="report">The report.</param>
        /// <param name="reportSettings">The settings.</param>
        /// <param name="suppressPreload">Pass true if the report has already been preloaded.</param>
        /// <returns>ReportResult.</returns>
        /// <exception cref="System.ArgumentException">@The report identifier resource is not a report.;reportId</exception>
        public ReportCompletionData PrepareReport(Model.Report report, ReportSettings reportSettings, bool suppressPreload = false)
        {
            if (report == null)
            {
                throw new ArgumentNullException("report");
            }
            if (reportSettings == null)
            {
                reportSettings = new ReportSettings( );
            }

            StructuredQuery structuredQuery;
            PreparedQuery   preparedReport;
            PreparedQuery   preparedRollup;

            using (EDC.ReadiNow.Diagnostics.Profiler.Measure("Prepare report run"))
                using (MessageContext messageContext = new MessageContext("Reports"))
                    using (new SecurityBypassContext( ))
                    {
                        // Get the structured query
                        structuredQuery = GetStructuredQuery(report, reportSettings, suppressPreload);

                        // Handle metadata-only request
                        if (reportSettings.RequireSchemaMetadata)
                        {
                            ReportResult reportResult = new ReportResult(report, structuredQuery, null, null, null, reportSettings);
                            return(new ReportCompletionData(reportResult));
                        }

                        // Prepare query settings
                        preparedReport = PrepareReportRun(structuredQuery, reportSettings);
                        preparedReport.QuerySettings.Hint = "Rpt-" + report.Id.ToString( );

                        // Handle rollups
                        preparedRollup = PrepareReportRollupRun(report, preparedReport.StructuredQuery, reportSettings, preparedReport.QuerySettings);
                    }

            Func <ReportResult> resultCallback = () =>
            {
                ReportResult reportResult = null;
                QueryResult  queryResult  = null;
                QueryResult  rollupResult = null;

                using (new SecurityBypassContext( ))
                {
                    // Execute the query
                    queryResult = QueryRunner.ExecuteQuery(preparedReport.StructuredQuery, preparedReport.QuerySettings);

                    // Execute the rollup query
                    if (preparedRollup.StructuredQuery != null)
                    {
                        rollupResult = QueryRunner.ExecuteQuery(preparedRollup.StructuredQuery, preparedRollup.QuerySettings);
                    }

                    // Package up the result.
                    reportResult = new ReportResult(report,
                                                    preparedReport.StructuredQuery, queryResult,
                                                    preparedRollup.ClientAggregate, rollupResult,
                                                    reportSettings);
                }

                return(reportResult);
            };

            // Create cache key (null indicates report is not cacheable)
            IQueryRunnerCacheKey reportCacheKey       = null;
            IQueryRunnerCacheKey rollupCacheKey       = null;
            ReportResultCacheKey reportResultCacheKey = null;

            reportCacheKey = QueryRunnerCacheKeyProvider.CreateCacheKey(preparedReport.StructuredQuery, preparedReport.QuerySettings);
            if (reportCacheKey != null)
            {
                if (preparedRollup.StructuredQuery != null)
                {
                    rollupCacheKey = QueryRunnerCacheKeyProvider.CreateCacheKey(preparedRollup.StructuredQuery, preparedRollup.QuerySettings);
                }
                reportResultCacheKey = new ReportResultCacheKey(reportSettings, reportCacheKey, rollupCacheKey);
            }

            // Create completion result
            ReportCompletionData completionData = new ReportCompletionData( );

            completionData.ResultCallback = resultCallback;
            completionData.ResultCacheKey = reportResultCacheKey;
            completionData.CacheContextDuringPreparation = CacheContext.GetContext( );

            return(completionData);
        }