/// <summary> /// Posts the save changes. /// </summary> /// <param name="dbContext">The database context.</param> public override void PostSaveChanges(Data.DbContext dbContext) { var rockContext = dbContext as RockContext; if (this.PostSaveAttributeValueHistoryCurrent) { var attributeValueHistoricalService = new AttributeValueHistoricalService(rockContext); var attributeValueHistoricalPreviousCurrentRow = attributeValueHistoricalService.Queryable().Where(a => a.AttributeValueId == this.Id && a.CurrentRowIndicator == true).FirstOrDefault(); var saveChangesDateTime = RockDateTime.Now; if (attributeValueHistoricalPreviousCurrentRow != null) { attributeValueHistoricalPreviousCurrentRow.CurrentRowIndicator = false; attributeValueHistoricalPreviousCurrentRow.ExpireDateTime = saveChangesDateTime; } var attributeValueHistoricalCurrent = AttributeValueHistorical.CreateCurrentRowFromAttributeValue(this, saveChangesDateTime); attributeValueHistoricalService.Add(attributeValueHistoricalCurrent); rockContext.SaveChanges(); } // If this a Person Attribute, Update the ModifiedDateTime on the Person that this AttributeValue is associated with if (this.EntityId.HasValue && AttributeCache.Get(this.AttributeId)?.EntityTypeId == EntityTypeCache.Get <Rock.Model.Person>().Id) { var currentDateTime = RockDateTime.Now; int personId = this.EntityId.Value; var qryPersonsToUpdate = new PersonService(rockContext).Queryable(true, true).Where(a => a.Id == personId); rockContext.BulkUpdate(qryPersonsToUpdate, p => new Person { ModifiedDateTime = currentDateTime, ModifiedByPersonAliasId = this.ModifiedByPersonAliasId }); } base.PostSaveChanges(dbContext); }
/// <summary> /// Clones this AttributeValueHistorical object to a new AttributeValueHistorical object /// </summary> /// <param name="source">The source.</param> /// <param name="deepCopy">if set to <c>true</c> a deep copy is made. If false, only the basic entity properties are copied.</param> /// <returns></returns> public static AttributeValueHistorical Clone(this AttributeValueHistorical source, bool deepCopy) { if (deepCopy) { return(source.Clone() as AttributeValueHistorical); } else { var target = new AttributeValueHistorical(); target.CopyPropertiesFrom(source); return(target); } }
/// <summary> /// Posts the save changes. /// </summary> /// <param name="dbContext">The database context.</param> public override void PostSaveChanges(Data.DbContext dbContext) { int?historyEntityId = (HistoryEntityId.HasValue && HistoryEntityId.Value > 0) ? HistoryEntityId.Value : this.EntityId; var rockContext = dbContext as RockContext; if (HistoryChanges != null && HistoryChanges.Any() && HistoryEntityTypeId.HasValue && historyEntityId.HasValue) { if (HistoryEntityTypeId.Value == EntityTypeCache.Get(typeof(Person)).Id) { HistoryService.SaveChanges(rockContext, typeof(Person), Rock.SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(), historyEntityId.Value, HistoryChanges, string.Empty, typeof(Attribute), AttributeId, true, this.ModifiedByPersonAliasId, dbContext.SourceOfChange); } else { HistoryService.SaveChanges(rockContext, typeof(Group), Rock.SystemGuid.Category.HISTORY_GROUP_CHANGES.AsGuid(), historyEntityId.Value, HistoryChanges, string.Empty, typeof(Attribute), AttributeId, true, this.ModifiedByPersonAliasId, dbContext.SourceOfChange); } } if (this.PostSaveAttributeValueHistoryCurrent) { var attributeValueHistoricalService = new AttributeValueHistoricalService(rockContext); var attributeValueHistoricalPreviousCurrentRow = attributeValueHistoricalService.Queryable().Where(a => a.AttributeValueId == this.Id && a.CurrentRowIndicator == true).FirstOrDefault(); var saveChangesDateTime = RockDateTime.Now; if (attributeValueHistoricalPreviousCurrentRow != null) { attributeValueHistoricalPreviousCurrentRow.CurrentRowIndicator = false; attributeValueHistoricalPreviousCurrentRow.ExpireDateTime = saveChangesDateTime; } var attributeValueHistoricalCurrent = AttributeValueHistorical.CreateCurrentRowFromAttributeValue(this, saveChangesDateTime); attributeValueHistoricalService.Add(attributeValueHistoricalCurrent); rockContext.SaveChanges(); } // If this a Person Attribute, Update the ModifiedDateTime on the Person that this AttributeValue is associated with if (this.EntityId.HasValue && AttributeCache.Get(this.AttributeId)?.EntityTypeId == EntityTypeCache.Get <Rock.Model.Person>().Id) { var currentDateTime = RockDateTime.Now; int personId = this.EntityId.Value; var qryPersonsToUpdate = new PersonService(rockContext).Queryable(true, true).Where(a => a.Id == personId); rockContext.BulkUpdate(qryPersonsToUpdate, p => new Person { ModifiedDateTime = currentDateTime, ModifiedByPersonAliasId = this.ModifiedByPersonAliasId }); } base.PostSaveChanges(dbContext); }
/// <summary> /// Posts the save changes. /// </summary> /// <param name="dbContext">The database context.</param> public override void PostSaveChanges(Data.DbContext dbContext) { var rockContext = dbContext as RockContext; if (this.PostSaveAttributeValueHistoryCurrent) { var attributeValueHistoricalService = new AttributeValueHistoricalService(rockContext); var attributeValueHistoricalPreviousCurrentRow = attributeValueHistoricalService.Queryable().Where(a => a.AttributeValueId == this.Id && a.CurrentRowIndicator == true).FirstOrDefault(); var saveChangesDateTime = RockDateTime.Now; if (attributeValueHistoricalPreviousCurrentRow != null) { attributeValueHistoricalPreviousCurrentRow.CurrentRowIndicator = false; attributeValueHistoricalPreviousCurrentRow.ExpireDateTime = saveChangesDateTime; } var attributeValueHistoricalCurrent = AttributeValueHistorical.CreateCurrentRowFromAttributeValue(this, saveChangesDateTime); attributeValueHistoricalService.Add(attributeValueHistoricalCurrent); rockContext.SaveChanges(); } // If this a Person Attribute, Update the ModifiedDateTime on the Person that this AttributeValue is associated with. // For example, if the FavoriteColor attribute of Ted Decker is changed from Red to Blue, we'll update Ted's Person.ModifiedDateTime. if (this.EntityId.HasValue && AttributeCache.Get(this.AttributeId)?.EntityTypeId == EntityTypeCache.Get <Rock.Model.Person>().Id) { // since this could get called several times (one for each of changed Attributes on a person), do a direct SQL to minimize overhead var currentDateTime = RockDateTime.Now; int personId = this.EntityId.Value; if (this.ModifiedByPersonAliasId.HasValue) { rockContext.Database.ExecuteSqlCommand( $"UPDATE [Person] SET [ModifiedDateTime] = @modifiedDateTime, [ModifiedByPersonAliasId] = @modifiedByPersonAliasId WHERE [Id] = @personId", new System.Data.SqlClient.SqlParameter("@modifiedDateTime", currentDateTime), new System.Data.SqlClient.SqlParameter("@modifiedByPersonAliasId", this.ModifiedByPersonAliasId.Value), new System.Data.SqlClient.SqlParameter("@personId", personId)); } else { rockContext.Database.ExecuteSqlCommand( $"UPDATE [Person] SET [ModifiedDateTime] = @modifiedDateTime, [ModifiedByPersonAliasId] = NULL WHERE [Id] = @personId", new System.Data.SqlClient.SqlParameter("@modifiedDateTime", currentDateTime), new System.Data.SqlClient.SqlParameter("@personId", personId)); } } base.PostSaveChanges(dbContext); }
/// <summary> /// Saves to attribute historical value table. /// </summary> /// <param name="dbContext">The database context.</param> /// <param name="entry">The entry.</param> /// <param name="attributeCache">The attribute cache.</param> /// <param name="saveToHistoryTable">if set to <c>true</c> [save to history table].</param> protected void SaveToHistoryTable(Rock.Data.DbContext dbContext, DbEntityEntry entry, AttributeCache attributeCache, bool saveToHistoryTable) { this.PostSaveAttributeValueHistoryCurrent = false; var oldValue = GetHistoryOldValue(entry); var newValue = GetHistoryNewValue(entry.State); if (oldValue == newValue || !attributeCache.EnableHistory) { return; } var formattedOldValue = GetHistoryFormattedValue(oldValue, attributeCache); // value changed and attribute.EnableHistory = true, so flag PostSaveAttributeValueHistoryCurrent this.PostSaveAttributeValueHistoryCurrent = true; var attributeValueHistoricalService = new AttributeValueHistoricalService(dbContext as RockContext); if (this.Id < 1) { return; } // this is an existing AttributeValue, so fetch the AttributeValue that is currently marked as CurrentRow for this attribute value (if it exists) bool hasAttributeValueHistoricalCurrentRow = attributeValueHistoricalService.Queryable().Where(a => a.AttributeValueId == this.Id && a.CurrentRowIndicator == true).Any(); if (!hasAttributeValueHistoricalCurrentRow) { // this is an existing AttributeValue but there isn't a CurrentRow AttributeValueHistorical for this AttributeValue yet, so create it off of the OriginalValues AttributeValueHistorical attributeValueHistoricalPreviousCurrentRow = new AttributeValueHistorical { AttributeValueId = this.Id, Value = oldValue, ValueFormatted = formattedOldValue, ValueAsNumeric = entry.OriginalValues["ValueAsNumeric"] as decimal?, ValueAsDateTime = entry.OriginalValues["ValueAsDateTime"] as DateTime?, ValueAsBoolean = entry.OriginalValues["ValueAsBoolean"] as bool?, ValueAsPersonId = entry.OriginalValues["ValueAsPersonId"] as int?, EffectiveDateTime = entry.OriginalValues["ModifiedDateTime"] as DateTime? ?? RockDateTime.Now, CurrentRowIndicator = true, ExpireDateTime = HistoricalTracking.MaxExpireDateTime }; attributeValueHistoricalService.Add(attributeValueHistoricalPreviousCurrentRow); } }
/// <summary> /// Copies the properties from another AttributeValueHistorical object to this AttributeValueHistorical object /// </summary> /// <param name="target">The target.</param> /// <param name="source">The source.</param> public static void CopyPropertiesFrom(this AttributeValueHistorical target, AttributeValueHistorical source) { target.Id = source.Id; target.AttributeValueId = source.AttributeValueId; target.CurrentRowIndicator = source.CurrentRowIndicator; target.EffectiveDateTime = source.EffectiveDateTime; target.ExpireDateTime = source.ExpireDateTime; target.ForeignGuid = source.ForeignGuid; target.ForeignKey = source.ForeignKey; target.Value = source.Value; target.ValueAsBoolean = source.ValueAsBoolean; target.ValueAsDateTime = source.ValueAsDateTime; target.ValueAsNumeric = source.ValueAsNumeric; target.ValueAsPersonId = source.ValueAsPersonId; target.ValueFormatted = source.ValueFormatted; target.CreatedDateTime = source.CreatedDateTime; target.ModifiedDateTime = source.ModifiedDateTime; target.CreatedByPersonAliasId = source.CreatedByPersonAliasId; target.ModifiedByPersonAliasId = source.ModifiedByPersonAliasId; target.Guid = source.Guid; target.ForeignId = source.ForeignId; }
/// <summary> /// Pres the save. /// </summary> /// <param name="dbContext">The database context.</param> /// <param name="entry">The entry.</param> public override void PreSaveChanges(Rock.Data.DbContext dbContext, System.Data.Entity.Infrastructure.DbEntityEntry entry) { var attributeCache = AttributeCache.Get(this.AttributeId); if (attributeCache != null) { // Check to see if this attribute value if for a Field or Image field type // ( we don't want BinaryFileFieldType as that type of attribute's file can be used by more than one attribute ) var field = attributeCache.FieldType.Field; if (field != null && ( field is Rock.Field.Types.FileFieldType || field is Rock.Field.Types.ImageFieldType)) { Guid?newBinaryFileGuid = null; Guid?oldBinaryFileGuid = null; if (entry.State == System.Data.Entity.EntityState.Added || entry.State == System.Data.Entity.EntityState.Modified) { newBinaryFileGuid = Value.AsGuidOrNull(); } if (entry.State == System.Data.Entity.EntityState.Modified || entry.State == System.Data.Entity.EntityState.Deleted) { if (entry.OriginalValues["Value"] != null) { oldBinaryFileGuid = entry.OriginalValues["Value"].ToString().AsGuidOrNull(); } } if (oldBinaryFileGuid.HasValue) { if (!newBinaryFileGuid.HasValue || !newBinaryFileGuid.Value.Equals(oldBinaryFileGuid.Value)) { var transaction = new Rock.Transactions.DeleteAttributeBinaryFile(oldBinaryFileGuid.Value); Rock.Transactions.RockQueue.TransactionQueue.Enqueue(transaction); } } if (newBinaryFileGuid.HasValue) { BinaryFileService binaryFileService = new BinaryFileService(( RockContext )dbContext); var binaryFile = binaryFileService.Get(newBinaryFileGuid.Value); if (binaryFile != null && binaryFile.IsTemporary) { binaryFile.IsTemporary = false; } } } // Check to see if this attribute is for a person or group, and if so, save to history table bool saveToHistoryTable = attributeCache.EntityTypeId.HasValue && (attributeCache.EntityTypeId.Value == EntityTypeCache.Get(typeof(Person)).Id || attributeCache.EntityTypeId.Value == EntityTypeCache.Get(typeof(Group)).Id); if (saveToHistoryTable || attributeCache.EnableHistory) { string oldValue = string.Empty; string newValue = string.Empty; HistoryEntityTypeId = attributeCache.EntityTypeId.Value; HistoryEntityId = EntityId; switch (entry.State) { case System.Data.Entity.EntityState.Added: { newValue = Value; break; } case System.Data.Entity.EntityState.Modified: { oldValue = entry.OriginalValues["Value"].ToStringSafe(); newValue = Value; break; } case System.Data.Entity.EntityState.Deleted: { HistoryEntityId = entry.OriginalValues["EntityId"].ToStringSafe().AsIntegerOrNull(); oldValue = entry.OriginalValues["Value"].ToStringSafe(); return; } } this.PostSaveAttributeValueHistoryCurrent = false; if (oldValue != newValue) { var formattedOldValue = oldValue.IsNotNullOrWhiteSpace() ? attributeCache.FieldType.Field.FormatValue(null, oldValue, attributeCache.QualifierValues, true) : string.Empty; var formattedNewValue = newValue.IsNotNullOrWhiteSpace() ? attributeCache.FieldType.Field.FormatValue(null, newValue, attributeCache.QualifierValues, true) : string.Empty; if (saveToHistoryTable) { HistoryChanges = new History.HistoryChangeList(); History.EvaluateChange(HistoryChanges, attributeCache.Name, formattedOldValue, formattedNewValue); } if (attributeCache.EnableHistory) { // value changed and attribute.EnableHistory = true, so flag PostSaveAttributeValueHistoryCurrent this.PostSaveAttributeValueHistoryCurrent = true; var attributeValueHistoricalService = new AttributeValueHistoricalService(dbContext as RockContext); if (this.Id > 0) { // this is an existing AttributeValue, so fetch the AttributeValue that is currently marked as CurrentRow for this attribute value (if it exists) bool hasAttributeValueHistoricalCurrentRow = attributeValueHistoricalService.Queryable().Where(a => a.AttributeValueId == this.Id && a.CurrentRowIndicator == true).Any(); if (!hasAttributeValueHistoricalCurrentRow) { // this is an existing AttributeValue but there isn't a CurrentRow AttributeValueHistorical for this AttributeValue yet, so create it off of the OriginalValues AttributeValueHistorical attributeValueHistoricalPreviousCurrentRow = new AttributeValueHistorical { AttributeValueId = this.Id, Value = oldValue, ValueFormatted = formattedOldValue, ValueAsNumeric = entry.OriginalValues["ValueAsNumeric"] as decimal?, ValueAsDateTime = entry.OriginalValues["ValueAsDateTime"] as DateTime?, ValueAsBoolean = entry.OriginalValues["ValueAsBoolean"] as bool?, ValueAsPersonId = entry.OriginalValues["ValueAsPersonId"] as int?, EffectiveDateTime = entry.OriginalValues["ModifiedDateTime"] as DateTime? ?? RockDateTime.Now, CurrentRowIndicator = true, ExpireDateTime = HistoricalTracking.MaxExpireDateTime }; attributeValueHistoricalService.Add(attributeValueHistoricalPreviousCurrentRow); } } } } } } base.PreSaveChanges(dbContext, entry); }
/// <summary> /// Saves to history table. /// </summary> /// <param name="dbContext">The database context.</param> /// <param name="entry">The entry.</param> /// <param name="attributeCache">The attribute cache.</param> /// <param name="saveToHistoryTable">if set to <c>true</c> [save to history table].</param> protected void SaveToHistoryTable(Rock.Data.DbContext dbContext, DbEntityEntry entry, AttributeCache attributeCache, bool saveToHistoryTable) { string oldValue = string.Empty; string newValue = string.Empty; HistoryEntityTypeId = attributeCache.EntityTypeId.Value; HistoryEntityId = EntityId; switch (entry.State) { case EntityState.Added: newValue = Value; break; case EntityState.Modified: oldValue = entry.OriginalValues["Value"].ToStringSafe(); newValue = Value; break; case EntityState.Deleted: HistoryEntityId = entry.OriginalValues["EntityId"].ToStringSafe().AsIntegerOrNull(); oldValue = entry.OriginalValues["Value"].ToStringSafe(); return; } this.PostSaveAttributeValueHistoryCurrent = false; if (oldValue == newValue) { return; } var formattedOldValue = oldValue.IsNotNullOrWhiteSpace() ? attributeCache.FieldType.Field.FormatValue(null, oldValue, attributeCache.QualifierValues, true) : string.Empty; var formattedNewValue = newValue.IsNotNullOrWhiteSpace() ? attributeCache.FieldType.Field.FormatValue(null, newValue, attributeCache.QualifierValues, true) : string.Empty; if (saveToHistoryTable) { HistoryChanges = new History.HistoryChangeList(); History.EvaluateChange(HistoryChanges, attributeCache.Name, formattedOldValue, formattedNewValue, attributeCache.FieldType.Field.IsSensitive()); } if (!attributeCache.EnableHistory) { return; } // value changed and attribute.EnableHistory = true, so flag PostSaveAttributeValueHistoryCurrent this.PostSaveAttributeValueHistoryCurrent = true; var attributeValueHistoricalService = new AttributeValueHistoricalService(dbContext as RockContext); if (this.Id < 1) { return; } // this is an existing AttributeValue, so fetch the AttributeValue that is currently marked as CurrentRow for this attribute value (if it exists) bool hasAttributeValueHistoricalCurrentRow = attributeValueHistoricalService.Queryable().Where(a => a.AttributeValueId == this.Id && a.CurrentRowIndicator == true).Any(); if (!hasAttributeValueHistoricalCurrentRow) { // this is an existing AttributeValue but there isn't a CurrentRow AttributeValueHistorical for this AttributeValue yet, so create it off of the OriginalValues AttributeValueHistorical attributeValueHistoricalPreviousCurrentRow = new AttributeValueHistorical { AttributeValueId = this.Id, Value = oldValue, ValueFormatted = formattedOldValue, ValueAsNumeric = entry.OriginalValues["ValueAsNumeric"] as decimal?, ValueAsDateTime = entry.OriginalValues["ValueAsDateTime"] as DateTime?, ValueAsBoolean = entry.OriginalValues["ValueAsBoolean"] as bool?, ValueAsPersonId = entry.OriginalValues["ValueAsPersonId"] as int?, EffectiveDateTime = entry.OriginalValues["ModifiedDateTime"] as DateTime? ?? RockDateTime.Now, CurrentRowIndicator = true, ExpireDateTime = HistoricalTracking.MaxExpireDateTime }; attributeValueHistoricalService.Add(attributeValueHistoricalPreviousCurrentRow); } }