Example #1
0
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="paramExpression">The parameter expression.</param>
        /// <param name="dataViewFilterOverrides">The data view filter overrides.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public Expression GetExpression(IService serviceInstance, ParameterExpression paramExpression, DataViewFilterOverrides dataViewFilterOverrides, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var cachedEntityType = EntityTypeCache.Read(EntityTypeId.Value);

            if (cachedEntityType != null && cachedEntityType.AssemblyName != null)
            {
                Type filteredEntityType = cachedEntityType.GetEntityType();

                if (filteredEntityType != null)
                {
                    Expression filterExpression = DataViewFilter != null?DataViewFilter.GetExpression(filteredEntityType, serviceInstance, paramExpression, dataViewFilterOverrides, errorMessages) : null;

                    Expression transformedExpression = GetTransformExpression(serviceInstance, paramExpression, filterExpression, errorMessages);
                    if (transformedExpression != null)
                    {
                        return(transformedExpression);
                    }

                    return(filterExpression);
                }
            }

            return(null);
        }
Example #2
0
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="paramExpression">The parameter expression.</param>
        /// <param name="dataViewFilterOverrides">The data view filter overrides.</param>
        /// <returns></returns>
        /// <exception cref="Rock.Reporting.RockReportingException">
        /// Unable to determine Assembly for EntityTypeId { EntityTypeId }
        /// or
        /// Unable to determine DataView EntityType for { dataViewEntityTypeCache }.
        /// or
        /// Unable to determine transform expression for TransformEntityTypeId: {TransformEntityTypeId}
        /// </exception>
        public Expression GetExpression(IService serviceInstance, ParameterExpression paramExpression, DataViewFilterOverrides dataViewFilterOverrides)
        {
            var dataViewEntityTypeCache = EntityTypeCache.Get(EntityTypeId.Value);

            if (dataViewEntityTypeCache?.AssemblyName == null)
            {
                throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"Unable to determine DataView Assembly for EntityTypeId { EntityTypeId }");
            }

            Type dataViewEntityTypeType = dataViewEntityTypeCache.GetEntityType();

            if (dataViewEntityTypeType == null)
            {
                throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"Unable to determine DataView EntityType for { dataViewEntityTypeCache }.");
            }

            // DataViews must have a DataViewFilter (something has gone wrong it doesn't have one)
            // Note that DataViewFilterId might be null even though DataViewFilter is not null
            // This is because the DataViewFilter might be just in memory and not saved to the database (for example, a Preview or a DynamicReport)
            if (this.DataViewFilter == null)
            {
                throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"DataViewFilter is null for DataView { this.Name } ({this.Id}).");
            }

            bool usePersistedValues = this.PersistedScheduleIntervalMinutes.HasValue && this.PersistedLastRefreshDateTime.HasValue;

            if (dataViewFilterOverrides != null)
            {
                // don't use persisted values if this DataView in the list of DataViews that should not be persisted due to override
                usePersistedValues = usePersistedValues && !dataViewFilterOverrides.IgnoreDataViewPersistedValues.Contains(this.Id);
            }

            // If dataViewFilterOverrides is null assume true in order to preserve current functionality.
            RockLogger.Log.Debug(RockLogDomains.Reporting, "{methodName} dataViewFilterOverrides: {@dataViewFilterOverrides} DataviewId: {DataviewId}", nameof(GetExpression), dataViewFilterOverrides, DataViewFilter.DataViewId);
            if (dataViewFilterOverrides == null || dataViewFilterOverrides.ShouldUpdateStatics)
            {
                DataViewService.AddRunDataViewTransaction(Id);
            }

            // We need to call GetExpression regardless of whether or not usePresistedValues is true so the child queries get their stats updated.
            var filterExpression = DataViewFilter != null?DataViewFilter.GetExpression(dataViewEntityTypeType, serviceInstance, paramExpression, dataViewFilterOverrides) : null;

            if (usePersistedValues)
            {
                // If this is a persisted DataView, get the ids for the expression by querying DataViewPersistedValue instead of evaluating all the filters
                var rockContext = serviceInstance.Context as RockContext;
                if (rockContext == null)
                {
                    rockContext = new RockContext();
                }

                var persistedValuesQuery = rockContext.DataViewPersistedValues.Where(a => a.DataViewId == this.Id);
                var ids = persistedValuesQuery.Select(v => v.EntityId);
                MemberExpression propertyExpression = Expression.Property(paramExpression, "Id");
                if (!(serviceInstance.Context is RockContext))
                {
                    // if this DataView doesn't use a RockContext get the EntityIds into memory as a List<int> then back into IQueryable<int> so that we aren't use multiple dbContexts
                    ids = ids.ToList().AsQueryable();
                }

                var idsExpression = Expression.Constant(ids.AsQueryable(), typeof(IQueryable <int>));

                Expression expression = Expression.Call(typeof(Queryable), "Contains", new Type[] { typeof(int) }, idsExpression, propertyExpression);

                return(expression);
            }
            else
            {
                if (dataViewEntityTypeCache.Id == EntityTypeCache.Get(typeof(Rock.Model.Person)).Id)
                {
                    var        qry = new PersonService(( RockContext )serviceInstance.Context).Queryable(this.IncludeDeceased);
                    Expression extractedFilterExpression = FilterExpressionExtractor.Extract <Rock.Model.Person>(qry, paramExpression, "p");
                    if (filterExpression == null)
                    {
                        filterExpression = extractedFilterExpression;
                    }
                    else
                    {
                        filterExpression = Expression.AndAlso(filterExpression, extractedFilterExpression);
                    }
                }

                if (this.TransformEntityTypeId.HasValue)
                {
                    Expression transformedExpression = GetTransformExpression(this.TransformEntityTypeId.Value, serviceInstance, paramExpression, filterExpression);
                    if (transformedExpression == null)
                    {
                        // if TransformEntityTypeId is defined, but we got null back, we'll get unexpected results, so throw an exception
                        throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"Unable to determine transform expression for TransformEntityTypeId: {TransformEntityTypeId}");
                    }

                    return(transformedExpression);
                }

                return(filterExpression);
            }
        }
Example #3
0
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="paramExpression">The parameter expression.</param>
        /// <param name="dataViewFilterOverrides">The data view filter overrides.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public Expression GetExpression(IService serviceInstance, ParameterExpression paramExpression, DataViewFilterOverrides dataViewFilterOverrides, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var cachedEntityType = EntityTypeCache.Get(EntityTypeId.Value);

            if (cachedEntityType?.AssemblyName == null)
            {
                return(null);
            }

            Type filteredEntityType = cachedEntityType.GetEntityType();

            if (filteredEntityType == null)
            {
                return(null);
            }

            bool usePersistedValues = this.PersistedScheduleIntervalMinutes.HasValue && this.PersistedLastRefreshDateTime.HasValue;

            if (dataViewFilterOverrides != null)
            {
                // don't use persisted values if this dataview is in the list of dataviews that should not be persisted due to override
                usePersistedValues = usePersistedValues && !dataViewFilterOverrides.IgnoreDataViewPersistedValues.Contains(this.Id);
            }

            DataViewService.AddRunDataViewTransaction(Id);

            if (usePersistedValues)
            {
                // If this is a persisted dataview, get the ids for the expression by querying DataViewPersistedValue instead of evaluating all the filters
                var rockContext = serviceInstance.Context as RockContext;
                if (rockContext == null)
                {
                    rockContext = new RockContext();
                }

                var persistedValuesQuery = rockContext.DataViewPersistedValues.Where(a => a.DataViewId == this.Id);
                var ids = persistedValuesQuery.Select(v => v.EntityId);
                MemberExpression propertyExpression = Expression.Property(paramExpression, "Id");
                if (!(serviceInstance.Context is RockContext))
                {
                    // if this DataView doesn't use a RockContext get the EntityIds into memory as as a List<int> then back into IQueryable<int> so that we aren't use multiple dbContexts
                    ids = ids.ToList().AsQueryable();
                }

                var idsExpression = Expression.Constant(ids.AsQueryable(), typeof(IQueryable <int>));

                Expression expression = Expression.Call(typeof(Queryable), "Contains", new Type[] { typeof(int) }, idsExpression, propertyExpression);

                return(expression);
            }
            else
            {
                Expression filterExpression = DataViewFilter != null?DataViewFilter.GetExpression(filteredEntityType, serviceInstance, paramExpression, dataViewFilterOverrides, errorMessages) : null;

                if (cachedEntityType.Id == EntityTypeCache.Get(typeof(Rock.Model.Person)).Id)
                {
                    var        qry = new PersonService(( RockContext )serviceInstance.Context).Queryable(this.IncludeDeceased);
                    Expression extractedFilterExpression = FilterExpressionExtractor.Extract <Rock.Model.Person>(qry, paramExpression, "p");
                    if (filterExpression == null)
                    {
                        filterExpression = extractedFilterExpression;
                    }
                    else
                    {
                        filterExpression = Expression.AndAlso(filterExpression, extractedFilterExpression);
                    }
                }

                Expression transformedExpression = GetTransformExpression(serviceInstance, paramExpression, filterExpression, errorMessages);
                if (transformedExpression != null)
                {
                    return(transformedExpression);
                }

                return(filterExpression);
            }
        }
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="serviceInstance">The service instance.</param>
        /// <param name="paramExpression">The parameter expression.</param>
        /// <param name="dataViewFilterOverrides">The data view filter overrides.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public Expression GetExpression(IService serviceInstance, ParameterExpression paramExpression, DataViewFilterOverrides dataViewFilterOverrides, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var cachedEntityType = EntityTypeCache.Get(EntityTypeId.Value);

            if (cachedEntityType != null && cachedEntityType.AssemblyName != null)
            {
                Type filteredEntityType = cachedEntityType.GetEntityType();

                if (filteredEntityType != null)
                {
                    bool usePersistedValues = this.PersistedScheduleIntervalMinutes.HasValue && this.PersistedLastRefreshDateTime.HasValue;
                    if (dataViewFilterOverrides != null)
                    {
                        usePersistedValues = usePersistedValues && !dataViewFilterOverrides.IgnoreDataViewPersistedValues.Contains(this.Id);
                    }

                    // don't use persisted values if there are dataViewFilterOverrides
                    if (usePersistedValues && dataViewFilterOverrides?.Any() == true)
                    {
                        usePersistedValues = false;
                    }

                    if (usePersistedValues)
                    {
                        // If this is a persisted dataview, get the ids for the expression by querying DataViewPersistedValue instead of evaluating all the filters
                        var rockContext = serviceInstance.Context as RockContext;
                        if (rockContext == null)
                        {
                            rockContext = new RockContext();
                        }

                        var persistedValuesQuery = rockContext.DataViewPersistedValues.Where(a => a.DataViewId == this.Id);
                        var ids = persistedValuesQuery.Select(v => v.EntityId);
                        MemberExpression propertyExpression = Expression.Property(paramExpression, "Id");
                        if (!(serviceInstance.Context is RockContext))
                        {
                            // if this DataView doesn't use a RockContext get the EntityIds into memory as as a List<int> then back into IQueryable<int> so that we aren't use multiple dbContexts
                            ids = ids.ToList().AsQueryable();
                        }

                        var idsExpression = Expression.Constant(ids.AsQueryable(), typeof(IQueryable <int>));

                        Expression expression = Expression.Call(typeof(Queryable), "Contains", new Type[] { typeof(int) }, idsExpression, propertyExpression);

                        return(expression);
                    }
                    else
                    {
                        Expression filterExpression = DataViewFilter != null?DataViewFilter.GetExpression(filteredEntityType, serviceInstance, paramExpression, dataViewFilterOverrides, errorMessages) : null;

                        Expression transformedExpression = GetTransformExpression(serviceInstance, paramExpression, filterExpression, errorMessages);
                        if (transformedExpression != null)
                        {
                            return(transformedExpression);
                        }

                        return(filterExpression);
                    }
                }
            }

            return(null);
        }