public static void AuditEntityAdded(Audit audit, EntityEntry objectStateEntry)
#endif
        {
            var entry = new AuditEntry(audit, objectStateEntry)
            {
                State = AuditEntryState.EntityAdded
            };


            // CHECK if the key should be resolved in POST Action
#if EF5 || EF6
            if (objectStateEntry.EntityKey.IsTemporary)
            {
                entry.DelayedKey = objectStateEntry;
            }
            AuditEntityAdded(entry, objectStateEntry.CurrentValues);
#elif EF7
    // TODO: We must check if the key IsTemporary! We can maybe use flag...
    //if (!objectStateEntry.IsKeySet)
    //{
                entry.DelayedKey = objectStateEntry;
            //}
            AuditEntityAdded(entry, objectStateEntry);
#endif

            audit.Entries.Add(entry);
        }
 public static Audit AutoSaveAudit()
 {
     var audit = new Audit();
     audit.CreatedBy = "ZZZ Projects";
     audit.Configuration.AutoSavePreAction = (context, audit1) => (context as TestContext).AuditEntries.AddRange(audit1.Entries);
     return audit;
 }
        /// <summary>Pre save changes.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="context">The context used to audits and saves all changes made.</param>
        public static void PreSaveChanges(Audit audit, DbContext context)
        {
#if EF5 || EF6
            var objectContext = context.GetObjectContext();
            objectContext.DetectChanges();

            var changes = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted);

            foreach (var objectStateEntry in changes)
            {
                if (objectStateEntry.IsRelationship)
                {
                    if (objectStateEntry.State == EntityState.Added && audit.Configuration.IncludeRelationAdded)
                    {
                        AuditRelationAdded(audit, objectStateEntry);
                    }
                    else if (objectStateEntry.State == EntityState.Deleted && audit.Configuration.IncludeRelationDeleted)
                    {
                        AuditRelationDeleted(audit, objectStateEntry);
                    }
                }
                else
                {
                    if (objectStateEntry.State == EntityState.Added && audit.Configuration.IncludeEntityAdded)
                    {
                        AuditEntityAdded(audit, objectStateEntry);
                    }
                    else if (objectStateEntry.State == EntityState.Deleted && audit.Configuration.IncludeEntityDeleted)
                    {
                        AuditEntityDeleted(audit, objectStateEntry);
                    }
                    else if (objectStateEntry.State == EntityState.Modified && audit.Configuration.IncludeEntityModified)
                    {
                        AuditEntityModified(audit, objectStateEntry);
                    }
                }
            }
#elif EF7
            context.ChangeTracker.DetectChanges();
            var manager = context.ChangeTracker.GetStateManager();
            var entries = manager.Entries;

            foreach (var entry in entries)
            {
                if (entry.EntityState == EntityState.Added)
                {
                    
                }
                else if (entry.EntityState == EntityState.Deleted)
                {

                }
                else if (entry.EntityState == EntityState.Modified)
                {
                    
                }
            }
#endif

        }
        public static Audit AutoSaveAudit()
        {
            var audit = new Audit();
#if EF5 || EF6
            audit.Configuration.AutoSavePreAction = (context, audit1) => (context as TestContext).AuditEntries.AddRange(audit1.Entries);
#endif

            return audit;
        }
        /// <summary>Audit entity deleted.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
        public static void AuditEntityDeleted(Audit audit, ObjectStateEntry objectStateEntry)
        {
            var entry = new AuditEntry(objectStateEntry)
            {
                State = AuditEntryState.EntityDeleted
            };

            AuditEntityDeleted(entry, objectStateEntry.OriginalValues);
            audit.Entries.Add(entry);
        }
        /// <summary>Audits and saves all changes made in this context to the underlying database.</summary>
        /// <param name="context">The context used to audits and saves all changes made.</param>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <returns>The number of objects written to the underlying database.</returns>
        public static int SaveChanges(this DbContext context, Audit audit)
        {
            AuditStateEntry.PreSaveChanges(audit, context);
            var result = context.SaveChanges();
            AuditStateEntry.PostSaveChanges(audit);

            if (audit.Configuration.AutoSaveAction != null)
            {
                audit.Configuration.AutoSaveAction(context, audit);
                context.SaveChanges();
            }

            return result;
        }
        /// <summary>Audits and saves all changes made in this context to the underlying database.</summary>
        /// <param name="context">The context used to audits and saves all changes made.</param>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <returns>The number of objects written to the underlying database.</returns>
        public static int SaveChanges(this DbContext context, Audit audit)
        {
            audit.PreSaveChanges(context);
            var rowAffecteds = context.SaveChanges();
            audit.PostSaveChanges();

            if (audit.CurrentOrDefaultConfiguration.AutoSavePreAction != null)
            {
                audit.CurrentOrDefaultConfiguration.AutoSavePreAction(context, audit);
                context.SaveChanges();
            }

            return rowAffecteds;
        }
        /// <summary>A DbContext extension method that saves the changes asynchronous.</summary>
        /// <param name="context">The context used to audits and saves all changes made.</param>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <returns>
        ///     A task that represents the asynchronous save operation. The task result contains the number of objects written
        ///     to the underlying database
        /// </returns>
        public static async Task<int> SaveChangesAsync(this DbContext context, Audit audit, CancellationToken cancellationToken)
        {
            audit.PreSaveChanges(context);
            var rowAffecteds = await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            audit.PostSaveChanges();

            if (audit.CurrentOrDefaultConfiguration.AutoSavePreAction != null)
            {
                audit.CurrentOrDefaultConfiguration.AutoSavePreAction(context, audit);
                await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }

            return rowAffecteds;
        }
        /// <summary>Audit entity added.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
        public static void AuditEntityAdded(Audit audit, ObjectStateEntry objectStateEntry)
        {
            var entry = new AuditEntry(objectStateEntry)
            {
                State = AuditEntryState.EntityAdded
            };

            // CHECK if the key should be resolved in POST Action
            if (objectStateEntry.EntityKey.IsTemporary)
            {
                entry.DelayedKey = objectStateEntry;
            }

            AuditEntityAdded(entry, objectStateEntry.CurrentValues);
            audit.Entries.Add(entry);
        }
        public static void AuditEntityDeleted(Audit audit, EntityEntry objectStateEntry)
#endif
        {
            var entry = new AuditEntry(audit, objectStateEntry)
            {
                State = AuditEntryState.EntityDeleted
            };


#if EF5 || EF6
            AuditEntityDeleted(entry, objectStateEntry.OriginalValues);
#elif EFCORE
            AuditEntityDeleted(entry, objectStateEntry);
#endif
            audit.Entries.Add(entry);
        }
        /// <summary>A DbContext extension method that saves the changes asynchronous.</summary>
        /// <param name="context">The context used to audits and saves all changes made.</param>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="cancellationToken">A CancellationToken to observe while waiting for the task to complete.</param>
        /// <returns>
        ///     A task that represents the asynchronous save operation. The task result contains the number of objects written
        ///     to the underlying database
        /// </returns>
        public static Task<int> SaveChangesAsync(this DbContext context, Audit audit, CancellationToken cancellationToken)
        {
            AuditStateEntry.PreSaveChanges(audit, context);
            var result = context.SaveChangesAsync(cancellationToken);
            AuditStateEntry.PostSaveChanges(audit);

            if (audit.Configuration.AutoSaveAsyncAction != null)
            {
                result.ContinueWith(x =>
                {
                    audit.Configuration.AutoSaveAsyncAction(context, audit, cancellationToken);
                    return x.Result;
                }, cancellationToken).ConfigureAwait(false);
            }

            return result;
        }
        /// <summary>Audit entity modified.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
        public static void AuditEntityModified(Audit audit, ObjectStateEntry objectStateEntry)
        {
            var entry = new AuditEntry(objectStateEntry)
            {
                State = AuditEntryState.EntityModified
            };

            if (audit.Configuration.IsSoftAdded != null && audit.Configuration.IsSoftAdded(objectStateEntry.Entity))
            {
                entry.State = AuditEntryState.EntitySoftAdded;
            }
            else if (audit.Configuration.IsSoftDeleted != null && audit.Configuration.IsSoftDeleted(objectStateEntry.Entity))
            {
                entry.State = AuditEntryState.EntitySoftDeleted;
            }

            AuditEntityModified(audit, entry, objectStateEntry.OriginalValues, objectStateEntry.CurrentValues);
            audit.Entries.Add(entry);
        }
        /// <summary>Posts a save changes.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        public static void PostSaveChanges(Audit audit)
        {
            foreach (var entry in audit.Entries)
            {
                if (entry.DelayedKey != null)
                {
                    var objectStateEntry = entry.DelayedKey as ObjectStateEntry;
                    if (objectStateEntry != null)
                    {
                        if (objectStateEntry.IsRelationship)
                        {
                            var values = objectStateEntry.CurrentValues;
                            var value_0 = (EntityKey) values.GetValue(0);
                            var value_1 = (EntityKey) values.GetValue(1);
                            var relationName_0 = values.GetName(0);
                            var relationName_1 = values.GetName(1);

                            foreach (var keyValue in value_0.EntityKeyValues)
                            {
                                var keyName = string.Concat(relationName_0, ";", keyValue.Key);
                                entry.Properties.Add(new AuditEntryProperty(keyName, null, keyValue.Value));
                            }

                            foreach (var keyValue in value_1.EntityKeyValues)
                            {
                                var keyName = string.Concat(relationName_1, ";", keyValue.Key);
                                entry.Properties.Add(new AuditEntryProperty(keyName, null, keyValue.Value));
                            }
                        }
                        else
                        {
                            foreach (var keyValue in objectStateEntry.EntityKey.EntityKeyValues)
                            {
                                var property = entry.Properties.First(x => x.PropertyName == keyValue.Key);
                                property.NewValue = keyValue.Value;
                            }
                        }
                    }
                }
            }
        }
        public static void AuditRelationDeleted(Audit audit, EntityEntry objectStateEntry)
#endif
        {
            var entry = new AuditEntry(audit, objectStateEntry)
            {
                State = AuditEntryState.RelationshipDeleted
            };

            var values = objectStateEntry.OriginalValues;
            for (var i = 0; i < values.FieldCount; i++)
            {
                var relationName = values.GetName(i);
                var value = (EntityKey) values.GetValue(i);
                foreach (var keyValue in value.EntityKeyValues)
                {
                    entry.Properties.Add(new AuditEntryProperty(entry, relationName, keyValue.Key, keyValue.Value, null));
                }
            }

            audit.Entries.Add(entry);
        }
        /// <summary>Audit relationship deleted.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
        public static void AuditRelationDeleted(Audit audit, ObjectStateEntry objectStateEntry)
        {
            var entry = new AuditEntry(objectStateEntry)
            {
                State = AuditEntryState.RelationshipDeleted
            };

            var values = objectStateEntry.OriginalValues;
            for (var i = 0; i < values.FieldCount; i++)
            {
                var relationName = values.GetName(i);
                var value = (EntityKey) values.GetValue(i);
                foreach (var keyValue in value.EntityKeyValues)
                {
                    // todo: better add a new property association?
                    var keyName = string.Concat(relationName, ";", keyValue.Key);
                    entry.Properties.Add(new AuditEntryProperty(keyName, keyValue.Value, null));
                }
            }

            audit.Entries.Add(entry);
        }
        public static void AuditEntityModified(Audit audit, AuditEntry entry, DbDataRecord orginalRecord, DbUpdatableDataRecord currentRecord, string prefix = "")
        {
            for (var i = 0; i < orginalRecord.FieldCount; i++)
            {
                var name = orginalRecord.GetName(i);
                var originalValue = orginalRecord.GetValue(i);
                var currentValue = currentRecord.GetValue(i);

                var valueRecord = originalValue as DbDataRecord;
                if (valueRecord != null)
                {
                    // Complex Type
                    AuditEntityModified(audit, entry, valueRecord, currentValue as DbUpdatableDataRecord, string.Concat(prefix, name, "."));
                }
                else
                {
                    if (audit.Configuration.IncludePropertyUnchanged || !Equals(currentValue, originalValue))
                    {
                        entry.Properties.Add(new AuditEntryProperty(string.Concat(prefix, name), originalValue, currentValue));
                    }
                }
            }
        }
        /// <summary>Audit relationship added.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
        public static void AuditRelationAdded(Audit audit, ObjectStateEntry objectStateEntry)
        {
            var entry = new AuditEntry(objectStateEntry)
            {
                State = AuditEntryState.RelationshipAdded
            };

            var values = objectStateEntry.CurrentValues;


            var value_0 = (EntityKey) values.GetValue(0);
            var value_1 = (EntityKey) values.GetValue(1);

            if (value_0.IsTemporary || value_1.IsTemporary)
            {
                entry.DelayedKey = objectStateEntry;
            }
            else
            {
                var relationName_0 = values.GetName(0);
                var relationName_1 = values.GetName(1);

                foreach (var keyValue in value_0.EntityKeyValues)
                {
                    var keyName = string.Concat(relationName_0, ";", keyValue.Key);
                    entry.Properties.Add(new AuditEntryProperty(keyName, null, keyValue.Value));
                }

                foreach (var keyValue in value_1.EntityKeyValues)
                {
                    var keyName = string.Concat(relationName_1, ";", keyValue.Key);
                    entry.Properties.Add(new AuditEntryProperty(keyName, null, keyValue.Value));
                }
            }

            audit.Entries.Add(entry);
        }
        public static void AuditRelationAdded(Audit audit, EntityEntry objectStateEntry)
#endif
        {
            var entry = new AuditEntry(audit, objectStateEntry)
            {
                State = AuditEntryState.RelationshipAdded
            };

            var values = objectStateEntry.CurrentValues;


            var leftKeys = (EntityKey) values.GetValue(0);
            var rightKeys = (EntityKey) values.GetValue(1);

            if (leftKeys.IsTemporary || rightKeys.IsTemporary)
            {
                entry.DelayedKey = objectStateEntry;
            }
            else
            {
                var leftRelationName = values.GetName(0);
                var rightRelationName = values.GetName(1);

                foreach (var keyValue in leftKeys.EntityKeyValues)
                {
                    entry.Properties.Add(new AuditEntryProperty(entry, leftRelationName, keyValue.Key, null, keyValue.Value));
                }

                foreach (var keyValue in rightKeys.EntityKeyValues)
                {
                    entry.Properties.Add(new AuditEntryProperty(entry, rightRelationName, keyValue.Key, null, keyValue.Value));
                }
            }

            audit.Entries.Add(entry);
        }
        /// <summary>Pre save changes.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="context">The context used to audits and saves all changes made.</param>
        public static void PreSaveChanges(Audit audit, DbContext context)
        {
            var objectContext = context.GetObjectContext();
            objectContext.DetectChanges();
            var changes = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted);

            foreach (var objectStateEntry in changes)
            {
                if (objectStateEntry.IsRelationship)
                {
                    if (objectStateEntry.State == EntityState.Added && audit.Configuration.IncludeRelationshipAdded)
                    {
                        AuditRelationAdded(audit, objectStateEntry);
                    }
                    else if (objectStateEntry.State == EntityState.Deleted && audit.Configuration.IncludeRelationshipDeleted)
                    {
                        AuditRelationDeleted(audit, objectStateEntry);
                    }
                }
                else
                {
                    if (objectStateEntry.State == EntityState.Added && audit.Configuration.IncludeEntityAdded)
                    {
                        AuditEntityAdded(audit, objectStateEntry);
                    }
                    else if (objectStateEntry.State == EntityState.Deleted && audit.Configuration.IncludeEntityDeleted)
                    {
                        AuditEntityDeleted(audit, objectStateEntry);
                    }
                    else if (objectStateEntry.State == EntityState.Modified && audit.Configuration.IncludeEntityModified)
                    {
                        AuditEntityModified(audit, objectStateEntry);
                    }
                }
            }
        }
        /// <summary>Updates audit entries after the save changes has been executed.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        public static void PostSaveChanges(Audit audit)
        {
            foreach (var entry in audit.Entries)
            {
                if (entry.DelayedKey != null)
                {
#if EF5 || EF6
                    var objectStateEntry = entry.DelayedKey as ObjectStateEntry;
#elif EFCORE
                    var objectStateEntry = entry.DelayedKey as EntityEntry;
#endif
                    if (objectStateEntry != null)
                    {
#if EF5 || EF6
                        if (objectStateEntry.IsRelationship)
                        {
                            var values            = objectStateEntry.CurrentValues;
                            var leftKeys          = (EntityKey)values.GetValue(0);
                            var rightKeys         = (EntityKey)values.GetValue(1);
                            var leftRelationName  = values.GetName(0);
                            var rightRelationName = values.GetName(1);

                            foreach (var keyValue in leftKeys.EntityKeyValues)
                            {
                                var auditEntryProperty = audit.Configuration.AuditEntryPropertyFactory != null?
                                                         audit.Configuration.AuditEntryPropertyFactory(new AuditEntryPropertyArgs(entry, objectStateEntry, leftRelationName, keyValue.Key, null, keyValue.Value)) :
                                                             new AuditEntryProperty();

                                auditEntryProperty.Build(entry, leftRelationName, keyValue.Key, null, keyValue.Value);
                                entry.Properties.Add(auditEntryProperty);
                            }

                            foreach (var keyValue in rightKeys.EntityKeyValues)
                            {
                                var auditEntryProperty = audit.Configuration.AuditEntryPropertyFactory != null?
                                                         audit.Configuration.AuditEntryPropertyFactory(new AuditEntryPropertyArgs(entry, objectStateEntry, rightRelationName, keyValue.Key, null, keyValue.Value)) :
                                                             new AuditEntryProperty();

                                auditEntryProperty.Build(entry, rightRelationName, keyValue.Key, null, keyValue.Value);
                                entry.Properties.Add(auditEntryProperty);
                            }
                        }
                        else
                        {
                            foreach (var keyValue in objectStateEntry.EntityKey.EntityKeyValues)
                            {
                                var property = entry.Properties.FirstOrDefault(x => x.InternalPropertyName == keyValue.Key);

                                // ENSURE the property is audited
                                if (property != null)
                                {
                                    property.NewValue = keyValue.Value;
                                }
                            }
                        }
                    }
#elif EFCORE
                        foreach (var keyValue in objectStateEntry.Metadata.GetKeys())
                        {
                            var key      = objectStateEntry.Property(keyValue.Properties[0].Name);
                            var property = entry.Properties.FirstOrDefault(x => x.InternalPropertyName == keyValue.Properties[0].Name);

                            // ENSURE the property is audited
                            if (property != null)
                            {
                                property.NewValue = key.CurrentValue;
                            }
                        }
                    }
#endif
                }
            }
        /// <summary>Audit entity deleted.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
#if EF5 || EF6
        public static void AuditEntityDeleted(Audit audit, ObjectStateEntry objectStateEntry)
示例#22
0
 public static void AuditRelationDeleted(Audit audit, AuditEntry entry, ObjectStateEntry objectStateEntry)
        /// <summary>Audit relationship added.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
#if EF5 || EF6
        public static void AuditRelationAdded(Audit audit, ObjectStateEntry objectStateEntry)
 /// <summary>Asynchronously audits and saves all changes made in this context to the underlying database.</summary>
 /// <param name="context">The context used to audits and saves all changes made.</param>
 /// <param name="audit">The audit to use to add changes made to the context.</param>
 /// <returns>
 ///     A task that represents the asynchronous save operation. The task result contains the number of objects written
 ///     to the underlying database
 /// </returns>
 public static Task<int> SaveChangesAsync(this DbContext context, Audit audit)
 {
     return context.SaveChangesAsync(audit, CancellationToken.None);
 }
示例#25
0
        /// <summary>Audit entity modified.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="entry">The entry.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
        /// <param name="orginalRecord">The original record.</param>
        /// <param name="currentRecord">The current record.</param>
        /// <param name="prefix">The prefix.</param>
        public static void AuditEntityModified(Audit audit, AuditEntry entry, ObjectStateEntry objectStateEntry, DbDataRecord orginalRecord, DbUpdatableDataRecord currentRecord, string prefix = "")
        {
            bool hasModified = false;

            for (var i = 0; i < orginalRecord.FieldCount; i++)
            {
                var name          = orginalRecord.GetName(i);
                var originalValue = orginalRecord.GetValue(i);
                var currentValue  = currentRecord.GetValue(i);

                if (audit.Configuration.UseNullForDBNullValue && originalValue == DBNull.Value)
                {
                    originalValue = null;
                }

                if (audit.Configuration.UseNullForDBNullValue && currentValue == DBNull.Value)
                {
                    currentValue = null;
                }

                var valueRecord = originalValue as DbDataRecord;
                if (valueRecord != null)
                {
                    // Complex Type
                    AuditEntityModified(audit, entry, objectStateEntry, valueRecord, currentValue as DbUpdatableDataRecord, string.Concat(prefix, name, "."));
                }

                else if (objectStateEntry.EntityKey.EntityKeyValues.Any(x => x.Key == name) ||
                         entry.Parent.CurrentOrDefaultConfiguration.IsAuditedProperty(entry.Entry, string.Concat(prefix, name)))
                {
                    var isKey = objectStateEntry.EntityKey.EntityKeyValues.Any(x => x.Key == name);

                    if (!audit.Configuration.IgnorePropertyUnchanged ||
                        isKey ||
                        !Equals(currentValue, originalValue))
                    {
                        var auditEntryProperty = entry.Parent.Configuration.AuditEntryPropertyFactory != null?
                                                 entry.Parent.Configuration.AuditEntryPropertyFactory(new AuditEntryPropertyArgs(entry, objectStateEntry, string.Concat(prefix, name), originalValue, currentValue)) :
                                                     new AuditEntryProperty();

                        auditEntryProperty.IsKey = isKey;

                        auditEntryProperty.Build(entry, string.Concat(prefix, name), originalValue, currentRecord, i);
                        entry.Properties.Add(auditEntryProperty);

                        if (!isKey)
                        {
                            hasModified = true;
                        }
                    }
                }
            }

            if (audit.Configuration.IgnoreEntityUnchanged)
            {
                if (!hasModified)
                {
                    entry.Properties.Clear();
                }
            }
        }
 public void Build(Audit parent, ObjectStateEntry entry)
示例#27
0
        private static void GrantDBContext_OnQtEFCommit(RpcContext rpcContext, Microsoft.EntityFrameworkCore.DbContext dbContext, DbInfo dbInfo, Z.EntityFramework.Plus.Audit audit)
        {
            var user = rpcContext.GetUserContext();

            if (haveAudit(user))
            {
                if (audit?.Entries == null)
                {
                    return;
                }

                var auditData = new List <AuditData>();
                try
                {
                    audit.Entries = audit.Entries.Where(x =>
                                                        x.State == AuditEntryState.EntityModified ||
                                                        x.State == AuditEntryState.EntityDeleted).ToList();

                    //修正空审计记录
                    if (audit.Entries.Count() == 0)
                    {
                        return;
                    }
                    auditData = AuditTool.AuditConvertToArgs(dbContext.Database, user, audit, dbInfo);
                    auditData?.ForEach(x =>
                    {
                        if (!string.IsNullOrEmpty(rpcContext.Args.rid))
                        {
                            x.TransactionId = rpcContext.Args.rid;
                        }
                    });
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, "GrantDBContext_OnQtEFCommit error.");
                }
                AuditTool.SaveAuditData(dbContext.Database, auditData, dbInfo);
            }
        }
        /// <summary>Adds audit entries before the save changes has been executed.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="context">The context used to audits and saves all changes made.</param>
        public static void PreSaveChanges(Audit audit, DbContext context)
        {
#if EF5 || EF6
            var objectContext = ((IObjectContextAdapter) context).ObjectContext;
            objectContext.DetectChanges();
            var changes = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted);
#elif EFCORE
            context.ChangeTracker.DetectChanges();
            var changes = context.ChangeTracker.Entries().Where(x => x.State == EntityState.Added ||
                                                                     x.State == EntityState.Modified ||
                                                                     x.State == EntityState.Deleted);
#endif

            foreach (var objectStateEntry in changes)
            {
#if EF5 || EF6
                // Relationship
                if (objectStateEntry.IsRelationship)
                {
                    // Relationship Added
                    if (objectStateEntry.State == EntityState.Added
                        && !audit.CurrentOrDefaultConfiguration.IgnoreRelationshipAdded)
                    {
                        AuditRelationAdded(audit, objectStateEntry);
                    }

                    // Relationship Deleted
                    else if (objectStateEntry.State == EntityState.Deleted
                             && !audit.CurrentOrDefaultConfiguration.IgnoreRelationshipDeleted)
                    {
                        AuditRelationDeleted(audit, objectStateEntry);
                    }
                }

                // Entity
                else
                {
#endif
                    // Entity Added
                    if (objectStateEntry.State == EntityState.Added
                        && !audit.CurrentOrDefaultConfiguration.IgnoreEntityAdded
                        && audit.CurrentOrDefaultConfiguration.IsAuditedEntity(objectStateEntry))
                    {
                        AuditEntityAdded(audit, objectStateEntry);
                    }

                    // Entity Deleted
                    else if (objectStateEntry.State == EntityState.Deleted
                             && !audit.CurrentOrDefaultConfiguration.IgnoreEntityDeleted
                             && audit.CurrentOrDefaultConfiguration.IsAuditedEntity(objectStateEntry))
                    {
                        AuditEntityDeleted(audit, objectStateEntry);
                    }

                    // Entity Modified
                    else if (objectStateEntry.State == EntityState.Modified
                             && audit.CurrentOrDefaultConfiguration.IsAuditedEntity(objectStateEntry))
                    {
                        var auditState = audit.CurrentOrDefaultConfiguration.GetEntityModifiedState(objectStateEntry);

                        // Entity Modified
                        if (auditState == AuditEntryState.EntityModified
                            && !audit.CurrentOrDefaultConfiguration.IgnoreEntityModified)
                        {
                            AuditEntityModified(audit, objectStateEntry, auditState);
                        }

                        // Entity Soft Added
                        else if (auditState == AuditEntryState.EntitySoftAdded
                                 && !audit.CurrentOrDefaultConfiguration.IgnoreEntitySoftAdded)
                        {
                            AuditEntityModified(audit, objectStateEntry, auditState);
                        }

                        // Entity Soft Deleted
                        else if (auditState == AuditEntryState.EntitySoftDeleted
                                 && !audit.CurrentOrDefaultConfiguration.IgnoreEntitySoftDeleted)
                        {
                            AuditEntityModified(audit, objectStateEntry, auditState);
                        }
                    }
#if EF5 || EF6
                }
#endif
            }
        }
示例#29
0
 public AuditEntryFactoryArgs(Audit audit, ObjectStateEntry objectStateEntry, AuditEntryState auditEntryState)
示例#30
0
        /// <summary>Constructor.</summary>
        /// <param name="parent">The audit parent.</param>
        /// <param name="entry">The object state entry.</param>
#if EF5 || EF6
        public AuditEntry(Audit parent, ObjectStateEntry entry)
 /// <summary>Asynchronously audits and saves all changes made in this context to the underlying database.</summary>
 /// <param name="context">The context used to audits and saves all changes made.</param>
 /// <param name="audit">The audit to use to add changes made to the context.</param>
 /// <returns>
 ///     A task that represents the asynchronous save operation. The task result contains the number of objects written
 ///     to the underlying database
 /// </returns>
 public static Task <int> SaveChangesAsync(this DbContext context, Audit audit)
 {
     return(context.SaveChangesAsync(audit, CancellationToken.None));
 }
示例#32
0
        /// <summary>Audit entity modified.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
#if EF5 || EF6
        public static void AuditEntityModified(Audit audit, ObjectStateEntry objectStateEntry, AuditEntryState state)
示例#33
0
        public static void AuditRelationAdded(Audit audit, EntityEntry objectStateEntry)
#endif
        {
            var entry = audit.Configuration.AuditEntryFactory != null?
                        audit.Configuration.AuditEntryFactory(new AuditEntryFactoryArgs(audit, objectStateEntry, AuditEntryState.RelationshipAdded)) :
                            new AuditEntry();

            entry.Build(audit, objectStateEntry);
            entry.State = AuditEntryState.RelationshipAdded;

            var values = objectStateEntry.CurrentValues;


            var leftKeys  = (EntityKey)values.GetValue(0);
            var rightKeys = (EntityKey)values.GetValue(1);

            if (leftKeys.IsTemporary || rightKeys.IsTemporary)
            {
                entry.DelayedKey = objectStateEntry;
            }
            else
            {
                var leftRelationName  = values.GetName(0);
                var rightRelationName = values.GetName(1);

                foreach (var keyValue in leftKeys.EntityKeyValues)
                {
                    var value = keyValue.Value;

                    if (audit.Configuration.UseNullForDBNullValue && value == DBNull.Value)
                    {
                        value = null;
                    }

                    var auditEntryProperty = entry.Parent.Configuration.AuditEntryPropertyFactory != null?
                                             entry.Parent.Configuration.AuditEntryPropertyFactory(new AuditEntryPropertyArgs(entry, objectStateEntry, leftRelationName, keyValue.Key, null, value)) :
                                                 new AuditEntryProperty();

                    auditEntryProperty.Build(entry, leftRelationName, keyValue.Key, null, value);
                    entry.Properties.Add(auditEntryProperty);
                }

                foreach (var keyValue in rightKeys.EntityKeyValues)
                {
                    var value = keyValue.Value;

                    if (audit.Configuration.UseNullForDBNullValue && value == DBNull.Value)
                    {
                        value = null;
                    }

                    var auditEntryProperty = entry.Parent.Configuration.AuditEntryPropertyFactory != null?
                                             entry.Parent.Configuration.AuditEntryPropertyFactory(new AuditEntryPropertyArgs(entry, objectStateEntry, rightRelationName, keyValue.Key, null, value)) :
                                                 new AuditEntryProperty();

                    auditEntryProperty.Build(entry, rightRelationName, keyValue.Key, null, value);
                    entry.Properties.Add(auditEntryProperty);
                }
            }

            audit.Entries.Add(entry);
        }
示例#34
0
        /// <summary>Audit entity added.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
#if EF5 || EF6
        public static void AuditEntityAdded(Audit audit, ObjectStateEntry objectStateEntry)
        /// <summary>Updates audit entries after the save changes has been executed.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        public static void PostSaveChanges(Audit audit)
        {
            foreach (var entry in audit.Entries)
            {
                if (entry.DelayedKey != null)
                {
#if EF5 || EF6
                    var objectStateEntry = entry.DelayedKey as ObjectStateEntry;
#elif EFCORE
                    var objectStateEntry = entry.DelayedKey as EntityEntry;
#endif
                    if (objectStateEntry != null)
                    {
#if EF5 || EF6
                        if (objectStateEntry.IsRelationship)
                        {
                            var values = objectStateEntry.CurrentValues;
                            var leftKeys = (EntityKey) values.GetValue(0);
                            var rightKeys = (EntityKey) values.GetValue(1);
                            var leftRelationName = values.GetName(0);
                            var rightRelationName = values.GetName(1);

                            foreach (var keyValue in leftKeys.EntityKeyValues)
                            {
                                entry.Properties.Add(new AuditEntryProperty(entry, leftRelationName, keyValue.Key, null, keyValue.Value));
                            }

                            foreach (var keyValue in rightKeys.EntityKeyValues)
                            {
                                entry.Properties.Add(new AuditEntryProperty(entry, rightRelationName, keyValue.Key, null, keyValue.Value));
                            }
                        }
                        else
                        {
                            foreach (var keyValue in objectStateEntry.EntityKey.EntityKeyValues)
                            {
                                var property = entry.Properties.FirstOrDefault(x => x.PropertyName == keyValue.Key);

                                // ENSURE the property is audited
                                if (property != null)
                                {
                                    property.NewValue = keyValue.Value;
                                }
                            }
                        }
                    }
#elif EFCORE
                        foreach (var keyValue in objectStateEntry.Metadata.GetKeys())
                        {
                            var key = objectStateEntry.Property(keyValue.Properties[0].Name);
                            var property = entry.Properties.FirstOrDefault(x => x.PropertyName == keyValue.Properties[0].Name);
                           
                            // ENSURE the property is audited
                            if (property != null)
                            {
                                property.NewValue = key.CurrentValue;
                            }
                        }
                    }
#endif
                }
            }
示例#36
0
        /// <summary>Adds audit entries before the save changes has been executed.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="context">The context used to audits and saves all changes made.</param>
        public static void PreSaveChanges(Audit audit, DbContext context)
        {
#if EF5 || EF6
            var objectContext = ((IObjectContextAdapter)context).ObjectContext;
            objectContext.DetectChanges();
            var changes = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted);
#elif EFCORE
            context.ChangeTracker.DetectChanges();
            var changes = context.ChangeTracker.Entries().Where(x => x.State == EntityState.Added ||
                                                                x.State == EntityState.Modified ||
                                                                x.State == EntityState.Deleted);
#endif

            foreach (var objectStateEntry in changes)
            {
#if EF5 || EF6
                // Relationship
                if (objectStateEntry.IsRelationship)
                {
                    // Relationship Added
                    if (objectStateEntry.State == EntityState.Added &&
                        !audit.CurrentOrDefaultConfiguration.IgnoreRelationshipAdded)
                    {
                        AuditRelationAdded(audit, objectStateEntry);
                    }

                    // Relationship Deleted
                    else if (objectStateEntry.State == EntityState.Deleted &&
                             !audit.CurrentOrDefaultConfiguration.IgnoreRelationshipDeleted)
                    {
                        AuditRelationDeleted(audit, objectStateEntry);
                    }
                }

                // Entity
                else
                {
#endif
                // Entity Added
                if (objectStateEntry.State == EntityState.Added &&
                    !audit.CurrentOrDefaultConfiguration.IgnoreEntityAdded &&
                    audit.CurrentOrDefaultConfiguration.IsAuditedEntity(objectStateEntry))
                {
                    AuditEntityAdded(audit, objectStateEntry);
                }

                // Entity Deleted
                else if (objectStateEntry.State == EntityState.Deleted &&
                         !audit.CurrentOrDefaultConfiguration.IgnoreEntityDeleted &&
                         audit.CurrentOrDefaultConfiguration.IsAuditedEntity(objectStateEntry))
                {
                    AuditEntityDeleted(audit, objectStateEntry);
                }

                // Entity Modified
                else if (objectStateEntry.State == EntityState.Modified &&
                         audit.CurrentOrDefaultConfiguration.IsAuditedEntity(objectStateEntry))
                {
                    var auditState = audit.CurrentOrDefaultConfiguration.GetEntityModifiedState(objectStateEntry);

                    // Entity Modified
                    if (auditState == AuditEntryState.EntityModified &&
                        !audit.CurrentOrDefaultConfiguration.IgnoreEntityModified)
                    {
                        AuditEntityModified(audit, objectStateEntry, auditState);
                    }

                    // Entity Soft Added
                    else if (auditState == AuditEntryState.EntitySoftAdded &&
                             !audit.CurrentOrDefaultConfiguration.IgnoreEntitySoftAdded)
                    {
                        AuditEntityModified(audit, objectStateEntry, auditState);
                    }

                    // Entity Soft Deleted
                    else if (auditState == AuditEntryState.EntitySoftDeleted &&
                             !audit.CurrentOrDefaultConfiguration.IgnoreEntitySoftDeleted)
                    {
                        AuditEntityModified(audit, objectStateEntry, auditState);
                    }
                }
#if EF5 || EF6
            }
#endif
            }
        }
        /// <summary>Updates audit entries after the save changes has been executed.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        public static void PostSaveChanges(Audit audit)
        {
            foreach (var entry in audit.Entries)
            {
                switch (entry.State)
                {
                case AuditEntryState.EntityAdded:
#if EF5 || EF6
                    AuditEntityAdded(entry, entry.Entry, entry.Entry.CurrentValues);
#elif EFCORE
                    AuditEntityAdded(entry, entry.Entry);
#endif
                    break;

                case AuditEntryState.EntityDeleted:
                case AuditEntryState.RelationshipDeleted:
                    break;

                case AuditEntryState.EntityModified:
                case AuditEntryState.EntitySoftAdded:
                case AuditEntryState.EntitySoftDeleted:
#if EF5 || EF6
                    foreach (var property in entry.Properties)
                    {
                        if (!property.IsValueSet)
                        {
                            var currentValue = property.DbUpdatableDataRecord.GetValue(property.DbUpdatableDataRecordPosition);

                            if (audit.Configuration.UseNullForDBNullValue && currentValue == DBNull.Value)
                            {
                                currentValue = null;
                            }
                            property.NewValue = currentValue;
                        }
                    }
#elif EFCORE
                    if (entry.State == AuditEntryState.EntityModified && entry.Entry.State == EntityState.Detached)
                    {
                        // Oops! It's has not beed modified but deleted
                        entry.State = AuditEntryState.EntityDeleted;

                        var listToRemove = entry.Properties.Where(x => !x.PropertyEntry.Metadata.IsKey()).ToList();
                        listToRemove.ForEach(x => entry.Properties.Remove(x));
                    }
                    else
                    {
                        foreach (var property in entry.Properties)
                        {
                            if (!property.IsValueSet)
                            {
                                var currentValue = property.PropertyEntry.CurrentValue;
                                property.NewValue = currentValue;
                            }
                        }
                    }
#endif
                    break;

                case AuditEntryState.RelationshipAdded:
#if EF5 || EF6
                    AuditRelationAdded(audit, entry, entry.Entry);
#endif
                    break;
                }
            }
            //            foreach (var entry in audit.Entries)
            //            {
            //                if (entry.DelayedKey != null)
            //                {
            //#if EF5 || EF6
            //                    var objectStateEntry = entry.DelayedKey as ObjectStateEntry;
            //#elif EFCORE
            //                    var objectStateEntry = entry.DelayedKey as EntityEntry;
            //#endif
            //                    if (objectStateEntry != null)
            //                    {
            //#if EF5 || EF6
            //                        if (objectStateEntry.IsRelationship)
            //                        {
            //                            var values = objectStateEntry.CurrentValues;
            //                            var leftKeys = (EntityKey) values.GetValue(0);
            //                            var rightKeys = (EntityKey) values.GetValue(1);
            //                            var leftRelationName = values.GetName(0);
            //                            var rightRelationName = values.GetName(1);

            //                            foreach (var keyValue in leftKeys.EntityKeyValues)
            //                            {
            //                                var auditEntryProperty = audit.Configuration.AuditEntryPropertyFactory != null ?
            //                                    audit.Configuration.AuditEntryPropertyFactory(new AuditEntryPropertyArgs(entry, objectStateEntry, leftRelationName, keyValue.Key, null, keyValue.Value)) :
            //                                    new AuditEntryProperty();

            //                                auditEntryProperty.Build(entry, leftRelationName, keyValue.Key, null, keyValue.Value);
            //                                entry.Properties.Add(auditEntryProperty);
            //                            }

            //                            foreach (var keyValue in rightKeys.EntityKeyValues)
            //                            {
            //                                var auditEntryProperty = audit.Configuration.AuditEntryPropertyFactory != null ?
            //                                    audit.Configuration.AuditEntryPropertyFactory(new AuditEntryPropertyArgs(entry, objectStateEntry, rightRelationName, keyValue.Key, null, keyValue.Value)) :
            //                                    new AuditEntryProperty();

            //                                auditEntryProperty.Build(entry, rightRelationName, keyValue.Key, null, keyValue.Value);
            //                                entry.Properties.Add(auditEntryProperty);
            //                            }
            //                        }
            //                        else
            //                        {
            //                            foreach (var keyValue in objectStateEntry.EntityKey.EntityKeyValues)
            //                            {
            //                                var property = entry.Properties.FirstOrDefault(x => x.InternalPropertyName == keyValue.Key);

            //                                // ENSURE the property is audited
            //                                if (property != null)
            //                                {
            //                                    property.NewValue = keyValue.Value;
            //                                }
            //                            }
            //                        }
            //                    }
            //#elif EFCORE
            //                        foreach (var keyValue in objectStateEntry.Metadata.GetKeys())
            //                        {
            //                            var key = objectStateEntry.Property(keyValue.Properties[0].Name);
            //                            var property = entry.Properties.FirstOrDefault(x => x.InternalPropertyName == keyValue.Properties[0].Name);

            //                            // ENSURE the property is audited
            //                            if (property != null)
            //                            {
            //                                property.NewValue = key.CurrentValue;
            //                            }
            //                        }
            //                    }
            //#endif
            //                }
            //}
        }
        /// <summary>Audit relationship added.</summary>
        /// <param name="audit">The audit to use to add changes made to the context.</param>
        /// <param name="objectStateEntry">The object state entry.</param>
#if EF5 || EF6
        public static void AuditRelationAdded(Audit audit, ObjectStateEntry objectStateEntry)