private IAuditEntity AuditEntity(DbEntityEntry entityEntry, AuditTypeInfo auditTypeInfo, DateTime auditDateTime, string user)
        {
            // Create audit entity.
            var dbSet       = this.Set(auditTypeInfo.AuditEntityType);
            var auditEntity = (IAuditEntity)dbSet.Create();

            dbSet.Add(auditEntity);

            // Copy the properties.
            var auditEntityEntry = this.Entry(auditEntity);

            if (entityEntry.State == EntityState.Added)
            {
                foreach (string propertyName in auditTypeInfo.AuditProperties)
                {
                    auditEntityEntry.Property(propertyName).CurrentValue = entityEntry.Property(propertyName).CurrentValue;
                }
            }
            else
            {
                foreach (string propertyName in auditTypeInfo.AuditProperties)
                {
                    auditEntityEntry.Property(propertyName).CurrentValue = entityEntry.Property(propertyName).OriginalValue;
                }
            }

            // Set the audit columns.
            auditEntityEntry.Property(AuditUpdatedColumnName).CurrentValue = auditDateTime;
            auditEntityEntry.Property(AuditUserColumnName).CurrentValue    = user;
            auditEntityEntry.Property(AuditTypeColumnName).CurrentValue    = entityEntry.State.ToAuditEntityState();

            return(auditEntity);
        }
        internal static AuditDbContextConfiguration GetAuditDbContextConfigurationFromXml()
        {
            var auditConfigurationSection = ConfigurationManager.GetSection("entityFramework.Audit") as AuditConfigurationSection ??
                                            new AuditConfigurationSection();

            var entityMapping = new List <AuditTypeInfo>();

            foreach (EntityElement entityElement in auditConfigurationSection.Entities)
            {
                var auditableEntityType = Type.GetType(entityElement.EntityType);
                if (auditableEntityType == null)
                {
                    throw new InvalidOperationException($"Auditable entity type '{entityElement.EntityType}' could not be loaded.");
                }

                var auditEntityType = Type.GetType(entityElement.AuditEntityType);
                if (auditEntityType == null)
                {
                    throw new InvalidOperationException($"Audit entity type '{entityElement.AuditEntityType}' could not be loaded.");
                }

                var auditTypeInfo = new AuditTypeInfo(auditableEntityType, auditEntityType);
                entityMapping.Add(auditTypeInfo);
            }

            return(new AuditDbContextConfiguration(auditConfigurationSection.AuditEnabled, auditConfigurationSection.AuditDateTimeKind, entityMapping.ToArray()));
        }
        /// <summary>
        ///     Registers and type for auditing.
        /// </summary>
        /// <param name="auditTypeInfo"></param>
        public void RegisterAuditType(AuditTypeInfo auditTypeInfo)
        {
            lock (this.auditTypes)
            {
                if (auditTypeInfo == null)
                {
                    throw new ArgumentNullException(nameof(auditTypeInfo));
                }

                // Extract the list of propeties to audit.
                var auditEntityType       = auditTypeInfo.AuditEntityType;
                var auditEntityProperties = auditEntityType.GetProperties();

                var auditableEntityType       = auditTypeInfo.AuditableEntityType;
                var auditableEntityProperties = auditableEntityType.GetProperties().ToDictionary(x => x.Name);

                if (this.auditTypes.ContainsKey(auditableEntityType))
                {
                    throw new ArgumentException($"Type {auditableEntityType.Name} is already registered for auditing.", nameof(auditableEntityType));
                }

                foreach (var property in auditEntityProperties)
                {
                    if (auditableEntityProperties.ContainsKey(property.Name))
                    {
                        if (property.PropertyType == auditableEntityProperties[property.Name].PropertyType)
                        {
                            auditTypeInfo.AuditProperties.Add(property.Name);
                        }
                    }
                }

                this.auditTypes.Add(auditableEntityType, auditTypeInfo);
            }
        }