Esempio n. 1
0
        /// <summary>
        /// Gets the query.
        /// </summary>
        /// <param name="dataViewGetQueryArgs">The data view get query arguments.</param>
        /// <returns></returns>
        /// <exception cref="Rock.Reporting.RockReportingException">
        /// Unable to determine DbContext for {this}
        /// or
        /// Unable to determine ServiceInstance for {this}
        /// or
        /// Unable to determine IService.Get for {this}
        /// </exception>
        public IQueryable <IEntity> GetQuery(DataViewGetQueryArgs dataViewGetQueryArgs)
        {
            var dbContext = dataViewGetQueryArgs.DbContext;

            if (dbContext == null)
            {
                dbContext = this.GetDbContext();
                if (dbContext == null)
                {
                    // this could happen if the EntityTypeId id refers to an assembly/type that doesn't exist anymore
                    // we'll just default to new RockContext(), but it'll likely fail when we try to get a ServiceInstance below if the entityType doesn't exist in an assembly
                    dbContext = new RockContext();
                }
            }

            IService serviceInstance = this.GetServiceInstance(dbContext);

            if (serviceInstance == null)
            {
                var entityTypeCache = EntityTypeCache.Get(this.EntityTypeId ?? 0);
                throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"Unable to determine ServiceInstance from DataView EntityType {entityTypeCache} for {this}");
            }

            var databaseTimeoutSeconds = dataViewGetQueryArgs.DatabaseTimeoutSeconds;

            if (databaseTimeoutSeconds.HasValue)
            {
                dbContext.Database.CommandTimeout = databaseTimeoutSeconds.Value;
            }

            var dataViewFilterOverrides         = dataViewGetQueryArgs.DataViewFilterOverrides;
            ParameterExpression paramExpression = serviceInstance.ParameterExpression;
            Expression          whereExpression = GetExpression(serviceInstance, paramExpression, dataViewFilterOverrides);

            MethodInfo getMethod = serviceInstance.GetType().GetMethod("Get", new Type[] { typeof(ParameterExpression), typeof(Expression), typeof(SortProperty) });

            if (getMethod == null)
            {
                throw new RockDataViewFilterExpressionException(this.DataViewFilter, $"Unable to determine IService.Get for Report: {this}");
            }

            var sortProperty = dataViewGetQueryArgs.SortProperty;

            if (sortProperty == null)
            {
                // if no sorting is specified, just sort by Id
                sortProperty = new SortProperty {
                    Direction = SortDirection.Ascending, Property = "Id"
                };
            }

            var getResult = getMethod.Invoke(serviceInstance, new object[] { paramExpression, whereExpression, sortProperty });
            var qry       = getResult as IQueryable <IEntity>;

            return(qry);
        }
Esempio n. 2
0
        /// <summary>
        /// Gets the ids.
        /// </summary>
        /// <param name="dataViewId">The data view identifier.</param>
        /// <returns></returns>
        public List <int> GetIds(int dataViewId)
        {
            var dataView             = Queryable().AsNoTracking().FirstOrDefault(d => d.Id == dataViewId);
            var dataViewGetQueryArgs = new DataViewGetQueryArgs
            {
                DatabaseTimeoutSeconds = 180,
            };

            return(dataView.GetQuery(dataViewGetQueryArgs).Select(a => a.Id).ToList());
        }
Esempio n. 3
0
        /// <summary>
        /// Persists the DataView to the database by updating the DataViewPersistedValues for this DataView. Returns true if successful
        /// </summary>
        /// <param name="databaseTimeoutSeconds">The database timeout seconds.</param>
        public void PersistResult(int?databaseTimeoutSeconds = null)
        {
            using (var dbContext = this.GetDbContext())
            {
                var persistStopwatch        = Stopwatch.StartNew();
                var dataViewFilterOverrides = new DataViewFilterOverrides();

                dataViewFilterOverrides.ShouldUpdateStatics = false;

                // set an override so that the Persisted Values aren't used when rebuilding the values from the DataView Query
                dataViewFilterOverrides.IgnoreDataViewPersistedValues.Add(this.Id);
                var dataViewGetQueryArgs = new DataViewGetQueryArgs
                {
                    DbContext = dbContext,
                    DataViewFilterOverrides = dataViewFilterOverrides,
                    DatabaseTimeoutSeconds  = databaseTimeoutSeconds,
                };

                var qry = this.GetQuery(dataViewGetQueryArgs);

                RockContext rockContext = dbContext as RockContext;
                if (rockContext == null)
                {
                    rockContext = new RockContext();
                }

                rockContext.Database.CommandTimeout = databaseTimeoutSeconds;
                var savedDataViewPersistedValues = rockContext.DataViewPersistedValues.Where(a => a.DataViewId == this.Id);

                var updatedEntityIdsQry = qry.Select(a => a.Id);

                if (!(rockContext 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
                    updatedEntityIdsQry = updatedEntityIdsQry.ToList().AsQueryable();
                }

                var persistedValuesToRemove    = savedDataViewPersistedValues.Where(a => !updatedEntityIdsQry.Any(x => x == a.EntityId));
                var persistedEntityIdsToInsert = updatedEntityIdsQry.Where(x => !savedDataViewPersistedValues.Any(a => a.EntityId == x)).ToList();

                var removeCount = persistedValuesToRemove.Count();
                if (removeCount > 0)
                {
                    // increase the batch size if there are a bunch of rows (and this is a narrow table with no references to it)
                    int?deleteBatchSize = removeCount > 50000 ? 25000 : ( int? )null;

                    int rowRemoved = rockContext.BulkDelete(persistedValuesToRemove, deleteBatchSize);
                }

                if (persistedEntityIdsToInsert.Any())
                {
                    List <DataViewPersistedValue> persistedValuesToInsert = persistedEntityIdsToInsert.OrderBy(a => a)
                                                                            .Select(a =>
                                                                                    new DataViewPersistedValue
                    {
                        DataViewId = this.Id,
                        EntityId   = a
                    }).ToList();

                    rockContext.BulkInsert(persistedValuesToInsert);
                }

                persistStopwatch.Stop();

                // Update the Persisted Refresh information.
                PersistedLastRefreshDateTime         = RockDateTime.Now;
                PersistedLastRunDurationMilliseconds = Convert.ToInt32(persistStopwatch.Elapsed.TotalMilliseconds);
            }
        }
            /// <summary>
            /// Called after the save operation has been executed
            /// </summary>
            /// <remarks>
            /// This method is only called if <see cref="M:Rock.Data.EntitySaveHook`1.PreSave" /> returns
            /// without error.
            /// </remarks>
            protected override void PostSave()
            {
                var rockContext = ( RockContext )this.RockContext;

                if (Entity.ConnectionStatus == null)
                {
                    Entity.ConnectionStatus = new ConnectionStatusService(rockContext).Get(Entity.ConnectionStatusId);
                }

                if (Entity.ConnectionStatus != null && Entity.ConnectionStatus.AutoInactivateState && Entity.ConnectionState != ConnectionState.Inactive)
                {
                    Entity.ConnectionState = ConnectionState.Inactive;
                    rockContext.SaveChanges();
                }

                if (Entity.ConnectionStatus.ConnectionStatusAutomations.Any())
                {
                    foreach (var connectionStatusAutomation in Entity.ConnectionStatus.ConnectionStatusAutomations)
                    {
                        bool isAutomationValid = true;
                        if (connectionStatusAutomation.DataViewId.HasValue)
                        {
                            // Get the dataview configured for the connection request
                            var dataViewService = new DataViewService(rockContext);
                            var dataview        = dataViewService.Get(connectionStatusAutomation.DataViewId.Value);
                            if (dataview != null)
                            {
                                var dataViewGetQueryArgs = new DataViewGetQueryArgs {
                                    DbContext = rockContext
                                };
                                isAutomationValid = dataview.GetQuery(dataViewGetQueryArgs).Any(a => a.Id == Entity.Id);
                            }
                        }

                        if (isAutomationValid && connectionStatusAutomation.GroupRequirementsFilter != GroupRequirementsFilter.Ignore)
                        {
                            // Group Requirement can't be meet when either placement group or placement group role id is missing
                            if (!Entity.AssignedGroupId.HasValue || !Entity.AssignedGroupMemberRoleId.HasValue)
                            {
                                isAutomationValid = false;
                            }
                            else
                            {
                                var isRequirementMeet   = true;
                                var group               = new GroupService(rockContext).Get(Entity.AssignedGroupId.Value);
                                var hasGroupRequirement = new GroupRequirementService(rockContext).Queryable().Where(a => (a.GroupId.HasValue && a.GroupId == group.Id) || (a.GroupTypeId.HasValue && a.GroupTypeId == group.GroupTypeId)).Any();
                                if (hasGroupRequirement)
                                {
                                    var requirementsResults = group.PersonMeetsGroupRequirements(
                                        rockContext,
                                        Entity.PersonAlias.PersonId,
                                        Entity.AssignedGroupMemberRoleId.Value);

                                    if (requirementsResults != null && requirementsResults
                                        .Where(a => a.MeetsGroupRequirement != MeetsGroupRequirement.NotApplicable)
                                        .Any(r =>
                                             r.MeetsGroupRequirement != MeetsGroupRequirement.Meets && r.MeetsGroupRequirement != MeetsGroupRequirement.MeetsWithWarning)
                                        )
                                    {
                                        isRequirementMeet = false;
                                    }
                                }

                                // connection request based on if group requirement is meet or not is added to list for status update
                                isAutomationValid = (connectionStatusAutomation.GroupRequirementsFilter == GroupRequirementsFilter.DoesNotMeet && !isRequirementMeet) ||
                                                    (connectionStatusAutomation.GroupRequirementsFilter == GroupRequirementsFilter.MustMeet && isRequirementMeet);
                            }
                        }

                        if (isAutomationValid)
                        {
                            Entity.ConnectionStatusId = connectionStatusAutomation.DestinationStatusId;

                            // disabled pre post processing in order to prevent circular loop that may arise due to status change.
                            rockContext.SaveChanges(true);
                        }
                    }
                }

                if (HistoryChangeList?.Any() == true)
                {
                    HistoryService.SaveChanges(rockContext, typeof(ConnectionRequest), Rock.SystemGuid.Category.HISTORY_CONNECTION_REQUEST.AsGuid(), Entity.Id, HistoryChangeList, true, Entity.ModifiedByPersonAliasId);
                }

                if (PersonHistoryChangeList?.Any() == true)
                {
                    var personAlias = Entity.PersonAlias ?? new PersonAliasService(rockContext).Get(Entity.PersonAliasId);
                    HistoryService.SaveChanges(
                        rockContext,
                        typeof(Person),
                        Rock.SystemGuid.Category.HISTORY_PERSON_CONNECTION_REQUEST.AsGuid(),
                        personAlias.PersonId,
                        PersonHistoryChangeList,
                        "Request",
                        typeof(ConnectionRequest),
                        Entity.Id,
                        true,
                        Entity.ModifiedByPersonAliasId,
                        rockContext.SourceOfChange);
                }

                base.PostSave();
            }