public virtual void Save(EntityChangeSet changeSet) { _unitOfWorkManager.WithUnitOfWork(() => { _changeSetRepository.Insert(changeSet); }); }
public virtual async Task SaveAsync(EntityChangeSet changeSet) { await _unitOfWorkManager.WithUnitOfWorkAsync(async() => { await _changeSetRepository.InsertAsync(changeSet); }); }
/// <summary> /// Updates change time, entity id and foreign keys after SaveChanges is called. /// </summary> private void UpdateChangeSet(EntityChangeSet changeSet) { foreach (var entityChange in changeSet.EntityChanges) { /* Update change time */ entityChange.ChangeTime = GetChangeTime(entityChange); /* Update entity id */ var entityEntry = entityChange.EntityEntry.As <EntityEntry>(); entityChange.EntityId = GetEntityId(entityEntry); /* Update foreign keys */ var foreignKeys = entityEntry.Metadata.GetForeignKeys(); foreach (var foreignKey in foreignKeys) { foreach (var property in foreignKey.Properties) { var propertyEntry = entityEntry.Property(property.Name); var propertyChange = entityChange.PropertyChanges.FirstOrDefault(pc => pc.PropertyName == property.Name); if (propertyChange == null) { if (!(propertyEntry.OriginalValue?.Equals(propertyEntry.CurrentValue) ?? propertyEntry.CurrentValue == null)) { // Add foreign key entityChange.PropertyChanges.Add(new EntityPropertyChange { NewValue = propertyEntry.CurrentValue.ToJsonString(), OriginalValue = propertyEntry.OriginalValue.ToJsonString(), PropertyName = property.Name, PropertyTypeFullName = property.ClrType.FullName }); } continue; } if (propertyChange.OriginalValue == propertyChange.NewValue) { var newValue = propertyEntry.CurrentValue.ToJsonString(); if (newValue == propertyChange.NewValue) { // No change entityChange.PropertyChanges.Remove(propertyChange); } else { // Update foreign key propertyChange.NewValue = newValue.TruncateWithPostfix(EntityPropertyChange.MaxValueLength); } } } } } }
public virtual EntityChangeSet CreateEntityChangeSet(DbContext context) { var changeSet = new EntityChangeSet { Reason = EntityChangeSetReasonProvider.Reason.TruncateWithPostfix(EntityChangeSet.MaxReasonLength), // Fill "who did this change" BrowserInfo = ClientInfoProvider.BrowserInfo.TruncateWithPostfix(EntityChangeSet.MaxBrowserInfoLength), ClientIpAddress = ClientInfoProvider.ClientIpAddress.TruncateWithPostfix(EntityChangeSet.MaxClientIpAddressLength), ClientName = ClientInfoProvider.ComputerName.TruncateWithPostfix(EntityChangeSet.MaxClientNameLength), ImpersonatorTenantId = AbpSession.ImpersonatorTenantId, ImpersonatorUserId = AbpSession.ImpersonatorUserId, TenantId = AbpSession.TenantId, UserId = AbpSession.UserId }; if (!IsEntityHistoryEnabled) { return(changeSet); } var objectContext = ((IObjectContextAdapter)context).ObjectContext; var relationshipChanges = objectContext.ObjectStateManager .GetObjectStateEntries(EntityState.Added | EntityState.Deleted) .Where(state => state.IsRelationship) .ToList(); foreach (var entityEntry in context.ChangeTracker.Entries()) { var shouldSaveEntityHistory = ShouldSaveEntityHistory(entityEntry); if (!shouldSaveEntityHistory && !entityEntry.HasAuditedProperties()) { continue; } var entityType = GetEntityType(objectContext, entityEntry.GetEntityBaseType()); var entityChange = CreateEntityChange(entityEntry, entityType); if (entityChange == null) { continue; } var entitySet = GetEntitySet(objectContext, entityType); var propertyChanges = new List <EntityPropertyChange>(); propertyChanges.AddRange(GetPropertyChanges(entityEntry, entityType, entitySet, shouldSaveEntityHistory)); propertyChanges.AddRange(GetRelationshipChanges(entityEntry, entityType, entitySet, relationshipChanges, shouldSaveEntityHistory)); if (!shouldSaveEntityHistory && propertyChanges.Count == 0) { continue; } entityChange.PropertyChanges = propertyChanges; changeSet.EntityChanges.Add(entityChange); } return(changeSet); }
public virtual void Save(EntityChangeSet changeSet) { if (!IsEntityHistoryEnabled) { return; } UpdateChangeSet(changeSet); if (changeSet.EntityChanges.Count == 0) { return; } using (var uow = UnitOfWorkManager.Begin(TransactionScopeOption.Suppress)) { EntityHistoryStore.Save(changeSet); uow.Complete(); } }
public virtual async Task SaveAsync(EntityChangeSet changeSet) { if (!IsEntityHistoryEnabled) { return; } if (changeSet.EntityChanges.Count == 0) { return; } UpdateChangeSet(changeSet); using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.Suppress)) { await EntityHistoryStore.SaveAsync(changeSet); await uow.CompleteAsync(); } }
public virtual EntityChangeSet CreateEntityChangeSet(ICollection <EntityEntry> entityEntries) { var changeSet = new EntityChangeSet { Reason = EntityChangeSetReasonProvider.Reason.TruncateWithPostfix(EntityChangeSet.MaxReasonLength), // Fill "who did this change" BrowserInfo = ClientInfoProvider.BrowserInfo.TruncateWithPostfix(EntityChangeSet.MaxBrowserInfoLength), ClientIpAddress = ClientInfoProvider.ClientIpAddress.TruncateWithPostfix(EntityChangeSet.MaxClientIpAddressLength), ClientName = ClientInfoProvider.ComputerName.TruncateWithPostfix(EntityChangeSet.MaxClientNameLength), ImpersonatorTenantId = AbpSession.ImpersonatorTenantId, ImpersonatorUserId = AbpSession.ImpersonatorUserId, TenantId = AbpSession.TenantId, UserId = AbpSession.UserId }; if (!IsEntityHistoryEnabled) { return(changeSet); } foreach (var entry in entityEntries) { var shouldSaveEntityHistory = ShouldSaveEntityHistory(entry); if (!shouldSaveEntityHistory && !HasAuditedProperties(entry)) { continue; } var entityChange = CreateEntityChange(entry, shouldSaveEntityHistory); if (entityChange == null) { continue; } changeSet.EntityChanges.Add(entityChange); } return(changeSet); }
/// <summary> /// Updates change time, entity id, Adds foreign keys, Removes/Updates property changes after SaveChanges is called. /// </summary> private void UpdateChangeSet(EntityChangeSet changeSet) { var entityChangesToRemove = new List <EntityChange>(); foreach (var entityChange in changeSet.EntityChanges) { var entityEntry = entityChange.EntityEntry.As <EntityEntry>(); var entityEntryType = ProxyHelper.GetUnproxiedType(entityEntry.Entity); var isAuditedEntity = IsTypeOfAuditedEntity(entityEntryType) == true; /* Update change time */ entityChange.ChangeTime = GetChangeTime(entityChange.ChangeType, entityEntry.Entity); /* Update entity id */ entityChange.EntityId = GetEntityId(entityEntry); /* Update property changes */ var trackedPropertyNames = entityChange.PropertyChanges.Select(pc => pc.PropertyName).ToList(); var additionalForeignKeys = entityEntry.Metadata.GetDeclaredReferencingForeignKeys() .Where(fk => trackedPropertyNames.Contains(fk.Properties[0].Name)) .ToList(); /* Add additional foreign keys from navigation properties */ foreach (var foreignKey in additionalForeignKeys) { foreach (var property in foreignKey.Properties) { var shouldSaveProperty = property.PropertyInfo == null // Shadow properties or if mapped directly to a field ? null : IsAuditedPropertyInfo(entityEntryType, property.PropertyInfo); if (shouldSaveProperty.HasValue && !shouldSaveProperty.Value) { continue; } var propertyEntry = entityEntry.Property(property.Name); var newValue = propertyEntry.GetNewValue()?.ToJsonString(); var oldValue = propertyEntry.GetOriginalValue()?.ToJsonString(); // Add foreign key entityChange.PropertyChanges.Add(CreateEntityPropertyChange(oldValue, newValue, property)); } } /* Update/Remove property changes */ var propertyChangesToRemove = new List <EntityPropertyChange>(); var foreignKeys = entityEntry.Metadata.GetForeignKeys(); foreach (var propertyChange in entityChange.PropertyChanges) { var propertyEntry = entityEntry.Property(propertyChange.PropertyName); // Take owner entity type if this is an owned entity var propertyEntityType = entityEntryType; if (entityEntry.Metadata.IsOwned()) { var ownerForeignKey = foreignKeys.First(fk => fk.IsOwnership); propertyEntityType = ownerForeignKey.PrincipalEntityType.ClrType; } var property = propertyEntry.Metadata; var isAuditedProperty = property.PropertyInfo != null && (IsAuditedPropertyInfo(propertyEntityType, property.PropertyInfo) ?? false); var isForeignKeyShadowProperty = property.IsShadowProperty() && foreignKeys.Any(fk => fk.Properties.Any(p => p.Name == propertyChange.PropertyName)); propertyChange.SetNewValue(propertyEntry.GetNewValue()?.ToJsonString()); if ((!isAuditedProperty && !isForeignKeyShadowProperty) || propertyChange.IsValuesEquals()) { // No change propertyChangesToRemove.Add(propertyChange); } } foreach (var propertyChange in propertyChangesToRemove) { entityChange.PropertyChanges.Remove(propertyChange); } if (!isAuditedEntity && entityChange.PropertyChanges.Count == 0) { entityChangesToRemove.Add(entityChange); } } foreach (var entityChange in entityChangesToRemove) { changeSet.EntityChanges.Remove(entityChange); } }
/// <summary> /// Updates change time, entity id, Adds foreign keys, Removes/Updates property changes after SaveChanges is called. /// </summary> private void UpdateChangeSet(EntityChangeSet changeSet) { var entityChangesToRemove = new List <EntityChange>(); foreach (var entityChange in changeSet.EntityChanges) { var entityEntry = entityChange.EntityEntry.As <EntityEntry>(); var isAuditedEntity = IsTypeOfAuditedEntity(entityEntry.Entity.GetType()) == true; /* Update change time */ entityChange.ChangeTime = GetChangeTime(entityChange.ChangeType, entityEntry.Entity); /* Update entity id */ entityChange.EntityId = GetEntityId(entityEntry); /* Update property changes */ var trackedPropertyNames = entityChange.PropertyChanges.Select(pc => pc.PropertyName); var trackedNavigationProperties = entityEntry.Navigations .Where(np => trackedPropertyNames.Contains(np.Metadata.Name)) .ToList(); var additionalForeignKeys = trackedNavigationProperties .Where(np => !trackedPropertyNames.Contains(np.Metadata.Name)) .Select(np => np.Metadata.ForeignKey) .Distinct() .ToList(); /* Add additional foreign keys from navigation properties */ foreach (var foreignKey in additionalForeignKeys) { foreach (var property in foreignKey.Properties) { var shouldSaveProperty = property.IsShadowProperty() ? null : IsAuditedPropertyInfo(property.PropertyInfo); if (shouldSaveProperty.HasValue && !shouldSaveProperty.Value) { continue; } var propertyEntry = entityEntry.Property(property.Name); // TODO: fix new value comparison before truncation var newValue = propertyEntry.GetNewValue()?.ToJsonString().TruncateWithPostfix(EntityPropertyChange.MaxValueLength); var oldValue = propertyEntry.GetOriginalValue()?.ToJsonString().TruncateWithPostfix(EntityPropertyChange.MaxValueLength); // Add foreign key entityChange.PropertyChanges.Add(CreateEntityPropertyChange(oldValue, newValue, property)); } } /* Update/Remove property changes */ var propertyChangesToRemove = new List <EntityPropertyChange>(); foreach (var propertyChange in entityChange.PropertyChanges) { var propertyEntry = entityEntry.Property(propertyChange.PropertyName); var isAuditedProperty = !propertyEntry.Metadata.IsShadowProperty() && IsAuditedPropertyInfo(propertyEntry.Metadata.PropertyInfo) == true; // TODO: fix new value comparison before truncation propertyChange.NewValue = propertyEntry.GetNewValue()?.ToJsonString().TruncateWithPostfix(EntityPropertyChange.MaxValueLength); if (!isAuditedProperty && propertyChange.OriginalValue == propertyChange.NewValue) { // No change propertyChangesToRemove.Add(propertyChange); } } foreach (var propertyChange in propertyChangesToRemove) { entityChange.PropertyChanges.Remove(propertyChange); } if (!isAuditedEntity && entityChange.PropertyChanges.Count == 0) { entityChangesToRemove.Add(entityChange); } } foreach (var entityChange in entityChangesToRemove) { changeSet.EntityChanges.Remove(entityChange); } }
public void Save(EntityChangeSet entityChangeSet) { }
/// <summary> /// Updates change time, entity id, Adds foreign keys, Removes/Updates property changes after SaveChanges is called. /// </summary> private void UpdateChangeSet(DbContext context, EntityChangeSet changeSet) { var entityChangesToRemove = new List <EntityChange>(); foreach (var entityChange in changeSet.EntityChanges) { var objectContext = context.As <IObjectContextAdapter>().ObjectContext; var entityEntry = entityChange.EntityEntry.As <DbEntityEntry>(); var typeOfEntity = entityEntry.GetEntityBaseType(); var isAuditedEntity = IsTypeOfAuditedEntity(typeOfEntity) == true; /* Update change time */ entityChange.ChangeTime = GetChangeTime(entityChange.ChangeType, entityEntry.Entity); /* Update entity id */ var entityType = GetEntityType(objectContext, typeOfEntity, useClrType: false); entityChange.EntityId = GetEntityId(entityEntry, entityType); /* Update property changes */ var trackedPropertyNames = entityChange.PropertyChanges.Select(pc => pc.PropertyName); var trackedNavigationProperties = entityType.NavigationProperties .Where(np => trackedPropertyNames.Contains(np.Name)) .ToList(); var additionalForeignKeys = trackedNavigationProperties .SelectMany(p => p.GetDependentProperties()) .Where(p => !trackedPropertyNames.Contains(p.Name)) .Distinct() .ToList(); /* Add additional foreign keys from navigation properties */ foreach (var foreignKey in additionalForeignKeys) { var propertyEntry = entityEntry.Property(foreignKey.Name); var propertyInfo = entityEntry.GetPropertyInfo(foreignKey.Name); var shouldSaveProperty = IsAuditedPropertyInfo(propertyInfo); if (shouldSaveProperty.HasValue && !shouldSaveProperty.Value) { continue; } // TODO: fix new value comparison before truncation var newValue = propertyEntry.GetNewValue()?.ToJsonString().TruncateWithPostfix(EntityPropertyChange.MaxValueLength); var oldValue = propertyEntry.GetOriginalValue()?.ToJsonString().TruncateWithPostfix(EntityPropertyChange.MaxValueLength); // Add foreign key entityChange.PropertyChanges.Add(CreateEntityPropertyChange(oldValue, newValue, propertyInfo)); } /* Update/Remove property changes */ var propertyChangesToRemove = new List <EntityPropertyChange>(); foreach (var propertyChange in entityChange.PropertyChanges) { var memberEntry = entityEntry.Member(propertyChange.PropertyName); if (!(memberEntry is DbPropertyEntry)) { // Skipping other types of properties // - Reference navigation properties (DbReferenceEntry) // - Collection navigation properties (DbCollectionEntry) continue; } var propertyEntry = memberEntry.As <DbPropertyEntry>(); var propertyInfo = entityEntry.GetPropertyInfo(propertyChange.PropertyName); var isAuditedProperty = IsAuditedPropertyInfo(propertyInfo) == true; // TODO: fix new value comparison before truncation propertyChange.NewValue = propertyEntry.GetNewValue()?.ToJsonString().TruncateWithPostfix(EntityPropertyChange.MaxValueLength); if (!isAuditedProperty && propertyChange.OriginalValue == propertyChange.NewValue) { // No change propertyChangesToRemove.Add(propertyChange); } } foreach (var propertyChange in propertyChangesToRemove) { entityChange.PropertyChanges.Remove(propertyChange); } if (!isAuditedEntity && entityChange.PropertyChanges.Count == 0) { entityChangesToRemove.Add(entityChange); } } foreach (var entityChange in entityChangesToRemove) { changeSet.EntityChanges.Remove(entityChange); } }
public virtual void Save(EntityChangeSet changeSet) { _changeSetRepository.Insert(changeSet); }
public virtual Task SaveAsync(EntityChangeSet changeSet) { return(_changeSetRepository.InsertAsync(changeSet)); }
public virtual EntityChangeSet CreateEntityChangeSet(ICollection <EntityEntry> entityEntries) { var changeSet = new EntityChangeSet { Reason = EntityChangeSetReasonProvider.Reason.TruncateWithPostfix(EntityChangeSet.MaxReasonLength), // Fill "who did this change" BrowserInfo = ClientInfoProvider.BrowserInfo.TruncateWithPostfix(EntityChangeSet.MaxBrowserInfoLength), ClientIpAddress = ClientInfoProvider.ClientIpAddress.TruncateWithPostfix(EntityChangeSet.MaxClientIpAddressLength), ClientName = ClientInfoProvider.ComputerName.TruncateWithPostfix(EntityChangeSet.MaxClientNameLength), ImpersonatorTenantId = AbpSession.ImpersonatorTenantId, ImpersonatorUserId = AbpSession.ImpersonatorUserId, TenantId = AbpSession.TenantId, UserId = AbpSession.UserId }; if (!IsEntityHistoryEnabled) { return(changeSet); } foreach (var entityEntry in entityEntries) { var typeOfEntity = ProxyHelper.GetUnproxiedType(entityEntry.Entity); var shouldTrackEntity = IsTypeOfTrackedEntity(typeOfEntity); if (shouldTrackEntity.HasValue && !shouldTrackEntity.Value) { continue; } if (!IsTypeOfEntity(typeOfEntity) && !entityEntry.Metadata.IsOwned()) { continue; } var shouldAuditEntity = IsTypeOfAuditedEntity(typeOfEntity); if (shouldAuditEntity.HasValue && !shouldAuditEntity.Value) { continue; } bool?shouldAuditOwnerEntity = null; bool?shouldAuditOwnerProperty = null; if (!shouldAuditEntity.HasValue && entityEntry.Metadata.IsOwned()) { // Check if owner entity has auditing attribute var ownerForeignKey = entityEntry.Metadata.GetForeignKeys().First(fk => fk.IsOwnership); var ownerEntityType = ownerForeignKey.PrincipalEntityType.ClrType; shouldAuditOwnerEntity = IsTypeOfAuditedEntity(ownerEntityType); if (shouldAuditOwnerEntity.HasValue && !shouldAuditOwnerEntity.Value) { continue; } var ownerPropertyInfo = ownerForeignKey.PrincipalToDependent.PropertyInfo; shouldAuditOwnerProperty = IsAuditedPropertyInfo(ownerEntityType, ownerPropertyInfo); if (shouldAuditOwnerProperty.HasValue && !shouldAuditOwnerProperty.Value) { continue; } } var entityChange = CreateEntityChange(entityEntry); if (entityChange == null) { continue; } var isAuditableEntity = (shouldAuditEntity.HasValue && shouldAuditEntity.Value) || (shouldAuditOwnerEntity.HasValue && shouldAuditOwnerEntity.Value) || (shouldAuditOwnerProperty.HasValue && shouldAuditOwnerProperty.Value); var isTrackableEntity = shouldTrackEntity.HasValue && shouldTrackEntity.Value; var shouldSaveAuditedPropertiesOnly = !isAuditableEntity && !isTrackableEntity; var propertyChanges = GetPropertyChanges(entityEntry, shouldSaveAuditedPropertiesOnly); if (propertyChanges.Count == 0) { continue; } entityChange.PropertyChanges = propertyChanges; changeSet.EntityChanges.Add(entityChange); } return(changeSet); }
public Task SaveAsync(EntityChangeSet entityChangeSet) { return(Task.CompletedTask); }
public static void Save(this IEntityHistoryHelper entityHistoryHelper, EntityChangeSet changeSet) { AsyncHelper.RunSync(() => entityHistoryHelper.SaveAsync(changeSet)); }
/// <summary> /// Updates change time, entity id and foreign keys after SaveChanges is called. /// </summary> private void UpdateChangeSet(DbContext context, EntityChangeSet changeSet) { foreach (var entityChange in changeSet.EntityChanges) { /* Update change time */ entityChange.ChangeTime = GetChangeTime(entityChange); /* Update entity id */ var entityEntry = entityChange.EntityEntry.As <DbEntityEntry>(); var entityType = GetEntityType(context.As <IObjectContextAdapter>().ObjectContext, entityEntry.GetEntityBaseType(), useClrType: false); entityChange.EntityId = GetEntityId(entityEntry, entityType); /* Update foreign keys */ var foreignKeys = entityType.NavigationProperties; foreach (var foreignKey in foreignKeys) { foreach (var property in foreignKey.GetDependentProperties()) { var propertyEntry = entityEntry.Property(property.Name); var propertyChange = entityChange.PropertyChanges.FirstOrDefault(pc => pc.PropertyName == property.Name); //make sure test case cover post saving (for foreign key update) if (propertyChange == null) { if (propertyEntry.HasChanged()) { var propertyInfo = entityEntry.GetPropertyInfo(property.Name); // Add foreign key entityChange.PropertyChanges.Add(new EntityPropertyChange { NewValue = propertyEntry.CurrentValue.ToJsonString(), OriginalValue = propertyEntry.OriginalValue.ToJsonString(), PropertyName = property.Name, PropertyTypeFullName = propertyInfo.PropertyType.FullName }); } continue; } if (propertyChange.OriginalValue == propertyChange.NewValue) { var newValue = propertyEntry.GetNewValue().ToJsonString(); if (newValue == propertyChange.NewValue) { // No change entityChange.PropertyChanges.Remove(propertyChange); } else { // Update foreign key propertyChange.NewValue = newValue.TruncateWithPostfix(EntityPropertyChange.MaxValueLength); } } } } } }