コード例 #1
0
        /// <summary>
        /// Identify cache dependencies.
        /// </summary>
        private static void IdentifyCacheDependencies(Report report, ReportToQueryConverterSettings settings, StructuredQuery query)
        {
            // Tell the cache what entities were referenced to return
            // the StructuredQuery result
            using (CacheContext cacheContext = CacheContext.GetContext( ))
            {
                cacheContext.Entities.Add(report.Id);

                if (query.Conditions != null)
                {
                    foreach (var condition in query.Conditions)
                    {
                        cacheContext.Entities.Add(condition.EntityId);

                        if (condition.Expression != null)
                        {
                            cacheContext.Entities.Add(condition.Expression.EntityId);
                        }
                    }
                }

                if (query.OrderBy != null)
                {
                    foreach (var orderBy in query.OrderBy)
                    {
                        if (orderBy.Expression != null)
                        {
                            cacheContext.Entities.Add(orderBy.Expression.EntityId);
                        }
                    }
                }

                if (query.SelectColumns != null)
                {
                    foreach (var column in query.SelectColumns)
                    {
                        cacheContext.Entities.Add(column.EntityId);

                        if (column.Expression != null)
                        {
                            cacheContext.Entities.Add(column.Expression.EntityId);
                        }
                    }
                }

                if (report.ReportOrderBys != null)
                {
                    foreach (var orderBy in report.ReportOrderBys)
                    {
                        if (orderBy != null)
                        {
                            cacheContext.Entities.Add(orderBy.Id);
                        }
                    }
                }
            }

            StructuredQueryHelper.IdentifyStructureCacheDependencies(query, settings.ConditionsOnly);
        }
コード例 #2
0
        /// <summary>
        /// Convert a <see cref="Report" /> to a <see cref="StructuredQuery" />.
        /// </summary>
        /// <param name="report">The <see cref="Report" /> to convert. This cannot be null.</param>
        /// <param name="settings"></param>
        /// <returns>
        /// The converted report.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">report</exception>
        public StructuredQuery Convert(Report report, ReportToQueryConverterSettings settings)
        {
            if (report == null)
            {
                throw new ArgumentNullException("report");
            }
            if (settings == null)
            {
                settings = ReportToQueryConverterSettings.Default;
            }

            StructuredQuery result;
            CachingReportToQueryConverterValue cacheValue;

            CachingReportToQueryConverterKey key = new CachingReportToQueryConverterKey(report, settings);

            using (MessageContext msg = new MessageContext("Reports"))
            {
                // Check cache
                bool doConvert = !TryGetValue(key, msg, out cacheValue);

                // Check for force recalculation
                if (settings.RefreshCachedStructuredQuery)
                {
                    msg.Append(() => "CachingReportToQueryConverter refreshed forced");
                    doConvert = true;
                }

                if (doConvert)
                {
                    lock (_syncRoot)
                    {
                        using (CacheContext cacheContext = new CacheContext( ))
                        {
                            result     = Converter.Convert(report, settings);
                            cacheValue = new CachingReportToQueryConverterValue(result);

                            Cache.Add(key, cacheValue);

                            // Add the cache context entries to the appropriate CacheInvalidator
                            _cacheInvalidator.AddInvalidations(cacheContext, key);
                        }
                    }
                }
                else if (CacheContext.IsSet( ))
                {
                    // Add the already stored changes that should invalidate this cache
                    // entry to any outer or containing cache contexts.
                    using (CacheContext cacheContext = CacheContext.GetContext( ))
                    {
                        cacheContext.AddInvalidationsFor(_cacheInvalidator, key);
                    }
                }
            }

            result = cacheValue.StructuredQuery;
            return(result);
        }
コード例 #3
0
 public FromEntityContext()
 {
     ReportNodeMap           = new Dictionary <long, Guid>();
     ReportNodeToEntityMap   = new Dictionary <long, Entity>();
     ReportColumnMap         = new Dictionary <long, Guid>();
     ColumnReferenceMap      = new Dictionary <Guid, long>();
     ReportExpressionMap     = new Dictionary <Guid, long>();
     InstanceExpressionMap   = new Dictionary <long, ScalarExpression>();
     ReportInvalidNodes      = new Dictionary <long, string>();
     ReportInvalidColumns    = new Dictionary <long, string>();
     ReportInvalidConditions = new Dictionary <long, string>();
     Settings = new ReportToQueryConverterSettings( );
 }
コード例 #4
0
        /// <summary>
        /// Convert a <see cref="Report" /> to a <see cref="StructuredQuery" />.
        /// </summary>
        /// <param name="report">The <see cref="Report" /> to convert. This cannot be null.</param>
        /// <param name="settings">Settings that control the converter behavior.</param>
        /// <returns>
        /// The converted report.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">report</exception>
        public StructuredQuery Convert(Report report, ReportToQueryConverterSettings settings)
        {
            if (report == null)
            {
                throw new ArgumentNullException("report");
            }
            if (settings == null)
            {
                settings = ReportToQueryConverterSettings.Default;
            }

            StructuredQuery query = StructuredQueryEntityHelper.ConvertReport(report, settings);

            IdentifyCacheDependencies(report, settings, query);

            return(query);
        }
コード例 #5
0
        /// <summary>
        /// Get the structured query, possibly from cache.
        /// </summary>
        /// <param name="report">The report to convert.</param>
        /// <param name="settings">The report run settings.</param>
        /// <param name="suppressPreload">True if we should suppress preloading.</param>
        /// <returns>The structured query.</returns>
        private StructuredQuery GetStructuredQuery(Model.Report report, ReportSettings settings, bool suppressPreload)
        {
            using (MessageContext msg = new MessageContext("Reports"))
            {
                StructuredQuery immutableStructuredQuery;
                StructuredQuery structuredQuery;

                bool useStructuredQueryCache = settings.UseStructuredQueryCache;

                ReportToQueryConverterSettings converterSettings = new ReportToQueryConverterSettings
                {
                    SuppressPreload = suppressPreload,
                    RefreshCachedStructuredQuery = settings.RefreshCachedStructuredQuery,
                    SchemaOnly = settings.RequireSchemaMetadata
                };

                if (settings != null && settings.UseStructuredQueryCache)
                {
                    // don't allow mutations of cached copy
                    immutableStructuredQuery = CachedReportToQueryConverter.Convert(report, converterSettings);
                }
                else
                {
                    // don't allow mutations, just so we can log it correctly
                    immutableStructuredQuery = NonCachedReportToQueryConverter.Convert(report, converterSettings);
                }

                structuredQuery = immutableStructuredQuery.DeepCopy( ); // so we can mutate it (in case we need to)

                // Logging
                msg.Append(() => new String('-', 50));
                msg.Append(() => "GetStructuredQuery");
                msg.Append(() => "suppressPreload = " + suppressPreload);
                msg.Append(() => "useStructuredQueryCache = " + useStructuredQueryCache);
                msg.Append(() => "Structured Query:\n" + StructuredQueryHelper.ToXml(immutableStructuredQuery));
                msg.Append(() => new String('-', 50));

                return(structuredQuery);
            }
        }
コード例 #6
0
        /// <summary>
        /// Converts a report into a structured query object.
        /// </summary>
        /// <param name="report">The report to convert</param>
        /// <param name="settings">Conversion settings.</param>
        /// <returns>The structured query.</returns>
        public static StructuredQuery ConvertReport(Report report, ReportToQueryConverterSettings settings)
        {
            if (report == null)
            {
                throw new ArgumentNullException();
            }
            if (settings == null)
            {
                settings = ReportToQueryConverterSettings.Default;
            }

            Report reportToLoad = report;

            if (report.RootNode == null)
            {
                throw new ArgumentException(string.Format("Invalid report '{0}' to load the structured query", report.Id));
            }

            // Preload the entities
            if (!settings.SuppressPreload)
            {
                ReportHelpers.PreloadQuery(reportToLoad.Id);
            }

            // Create context that contains information for conversion
            FromEntityContext fromEntityContext = new FromEntityContext {
                Report = reportToLoad, Settings = settings
            };

            // Convet the report entity
            StructuredQuery sq = BuildStructuredQuery(fromEntityContext, settings);

            // Attach the report to the structured query (why??)
            sq.Report = report;

            return(sq);
        }
コード例 #7
0
        /// <summary>
        /// Build the actual structured query object.
        /// </summary>
        private static StructuredQuery BuildStructuredQuery(FromEntityContext context, ReportToQueryConverterSettings settings)
        {
            Report report = context.Report;

            using (Profiler.Measure("Report {0} to StructuredQuery", report.Id))
            {
                StructuredQuery sq = new StructuredQuery(false);

                // Build up query starting with the root node
                using (Profiler.Measure("Query Tree"))
                {
                    sq.RootEntity = BuildReportNode(report.RootNode, context);
                }

                // then the list of select columns
                using (Profiler.Measure("Columns"))
                {
                    sq.SelectColumns = BuildSelectColumns(report.ReportColumns, context, settings);
                }

                // and then the list query conditions
                using (Profiler.Measure("Conditions"))
                {
                    sq.Conditions = BuildQueryConditions(report.HasConditions, context, settings);
                }

                // finally build up the list of order by items
                sq.OrderBy = BuildOrderBy(report.ReportOrderBys, context, settings);

                // Hook up the references
                ResolveReferences(sq, report, context);

                // Report back any errors
                sq.InvalidReportInformation = new Dictionary <string, Dictionary <long, string> >
                {
                    { "nodes", context.ReportInvalidNodes },
                    { "columns", context.ReportInvalidColumns },
                    { "conditions", context.ReportInvalidConditions }
                };

                return(sq);
            }
        }
コード例 #8
0
        /// <summary>
        /// Builds the order by collection.
        /// </summary>
        /// <param name="reportOrderBys">The report order bys.</param>
        /// <param name="context">The context.</param>
        /// <param name="settings">Conversion settings.</param>
        /// <returns>List{OrderByItem}.</returns>
        internal static List <OrderByItem> BuildOrderBy(IEntityCollection <ReportOrderBy> reportOrderBys, FromEntityContext context, ReportToQueryConverterSettings settings)
        {
            List <OrderByItem> orderByItems = new List <OrderByItem>();

            if (context.Settings.ConditionsOnly)
            {
                return(orderByItems); // don't bother converting them (e.g. for use in security)
            }

            foreach (ReportOrderBy reportOrderBy in reportOrderBys.OrderBy(rob => rob.OrderPriority))
            {
                ScalarExpression expression = BuildExpression(reportOrderBy.OrderByExpression, context);
                if (expression == null)
                {
                    EventLog.Application.WriteWarning("the order expression id: {0} is invalid.", reportOrderBy.OrderByExpression != null ? reportOrderBy.OrderByExpression.Id.ToString() : "null");
                    continue;
                }

                //the orderby expression is ColumnReferenceExpression, the referenced report column must exists
                if (context.ColumnReferenceMap.ContainsKey(expression.ExpressionId) &&
                    context.ReportColumnMap.ContainsKey(context.ColumnReferenceMap[expression.ExpressionId]))
                {
                    OrderByItem orderByItem = new OrderByItem
                    {
                        Direction =
                            reportOrderBy.ReverseOrder ?? false
                                    ? OrderByDirection.Descending
                                    : OrderByDirection.Ascending,
                        Expression = expression
                    };

                    orderByItems.Add(orderByItem);
                }
            }

            return(orderByItems);
        }
コード例 #9
0
        /// <summary>
        /// Builds the query conditions.
        /// </summary>
        /// <param name="reportConditions">The report conditions.</param>
        /// <param name="context">The context.</param>
        /// <param name="settings">Conversion settings.</param>
        /// <returns>List{QueryCondition}.</returns>
        internal static List <QueryCondition> BuildQueryConditions(IEntityCollection <ReportCondition> reportConditions, FromEntityContext context, ReportToQueryConverterSettings settings)
        {
            List <QueryCondition> queryConditions = new List <QueryCondition>();

            foreach (ReportCondition reportCondition in reportConditions)
            {
                // TODO Sort out analyser field crap (i.e. hidden/display name etc)?? Do we need this??
                ConditionType conditionType = ConditionType.Unspecified;
                if (reportCondition.Operator != null)
                {
                    string[] conditionOperatorParts = reportCondition.Operator.Alias.Split(':');
                    string   conditionOperator      = conditionOperatorParts.Length == 2 ? conditionOperatorParts[1].Substring(4) : conditionOperatorParts[0].Substring(4);
                    conditionType = (ConditionType)Enum.Parse(typeof(ConditionType), conditionOperator, true);
                }

                ScalarExpression scalarExpression = null;

                if (reportCondition.ConditionExpression == null)
                {
                    context.ReportInvalidConditions[reportCondition.Id] = reportCondition.Name;
                    if (!settings.SchemaOnly)
                    {
                        continue;
                    }
                }
                else
                {
                    scalarExpression = BuildExpression(reportCondition.ConditionExpression, context);
                    if (scalarExpression == null)
                    {
                        EventLog.Application.WriteWarning("the condition expression id: {0} is invalid.", reportCondition.ConditionExpression.Id.ToString());
                        if (!settings.SchemaOnly)
                        {
                            continue; // TODO: log warning .. should we just abort the query if it refers to an invalid expression in a condition .. because it means we'll get more rows.
                        }
                    }
                }

                QueryCondition queryCondition = new QueryCondition
                {
                    EntityId   = reportCondition.Id,
                    Operator   = conditionType,
                    Expression = scalarExpression
                };
                BuildConditionParameter(reportCondition, queryCondition, context);
                queryConditions.Add(queryCondition);
            }
            return(queryConditions);
        }
コード例 #10
0
        /// <summary>
        /// Builds the select columns.
        /// </summary>
        /// <param name="reportColumns">The report columns.</param>
        /// <param name="context">The context.</param>
        /// <param name="settings">Conversion settings.</param>
        /// <returns>List{SelectColumn}.</returns>
        internal static List <SelectColumn> BuildSelectColumns(IEntityCollection <ReportColumn> reportColumns, FromEntityContext context, ReportToQueryConverterSettings settings)
        {
            List <SelectColumn> columns = new List <SelectColumn>();
            // Order the columns based on position
            IEnumerable <ReportColumn> orderedReportColumns = reportColumns.OrderBy(rc => rc.ColumnDisplayOrder);

            foreach (ReportColumn orderedReportColumn in orderedReportColumns)
            {
                ScalarExpression scalarExpression = null;
                if (orderedReportColumn.ColumnExpression == null)
                {
                    context.ReportInvalidColumns[orderedReportColumn.Id] = orderedReportColumn.Name;
                    if (!settings.SchemaOnly)
                    {
                        continue;
                    }
                }
                else
                {
                    scalarExpression = BuildExpression(orderedReportColumn.ColumnExpression, context);
                    if (scalarExpression == null)
                    {
                        EventLog.Application.WriteWarning("the column expression id: {0} is invalid.", orderedReportColumn.ColumnExpression.Id.ToString());
                        context.ReportInvalidColumns[orderedReportColumn.Id] = orderedReportColumn.Name;
                        if (!settings.SchemaOnly)
                        {
                            continue;
                        }
                    }
                }

                Guid         columnId     = Guid.NewGuid();
                SelectColumn selectColumn = new SelectColumn
                {
                    IsHidden    = orderedReportColumn.ColumnIsHidden ?? false,
                    DisplayName = orderedReportColumn.Name,
                    Expression  = scalarExpression,
                    ColumnId    = columnId,
                    EntityId    = orderedReportColumn.Id
                };
                context.ReportColumnMap[orderedReportColumn.Id] = columnId;
                columns.Add(selectColumn);
            }
            return(columns);
        }
コード例 #11
0
 /// <summary>
 /// Constructor
 /// </summary>
 internal CachingReportToQueryConverterKey(Report report, ReportToQueryConverterSettings settings)
 {
     ReportId       = report.Id;
     ConditionsOnly = settings.ConditionsOnly;
     _hashCode      = GenerateHashCode();
 }