コード例 #1
0
        private void WriteKeys(AuditEntryState state)
        {
            var keys = state.EntityType.KeyMembers;

            if (keys == null)
            {
                return;
            }

            var currentValues = state.IsDeleted
                ? state.ObjectStateEntry.OriginalValues
                : state.ObjectStateEntry.CurrentValues;

            foreach (var keyMember in keys)
            {
                var auditkey = new AuditKey();
                try
                {
                    var name = keyMember.Name;
                    auditkey.Name = name;
                    auditkey.Type = GetType(keyMember);

                    var value = currentValues.GetValue(name);
                    value = FormatValue(state, name, value);

                    auditkey.Value = value;
                }
                catch (Exception ex)
                {
                    Trace.TraceError(ex.Message);
                    auditkey.Value = _errorText;
                }
                state.AuditEntity.Keys.Add(auditkey);
            }
        }
コード例 #2
0
        /// <summary>
        /// Updates the <see cref="AuditLog" /> from the current <see cref="ObjectContext" /> changes.
        /// </summary>
        /// <param name="auditLog">The audit log.</param>
        /// <returns></returns>
        public AuditLog UpdateLog(AuditLog auditLog)
        {
            if (auditLog == null)
            {
                throw new ArgumentNullException("auditLog");
            }

            // must call to make sure changes are detected
            ObjectContext.DetectChanges();

            var entityState = EntityState.Modified;

            if (Configuration.IncludeInserts)
            {
                entityState = entityState | EntityState.Added;
            }
            if (Configuration.IncludeDeletes)
            {
                entityState = entityState | EntityState.Deleted;
            }

            var changes = ObjectContext
                          .ObjectStateManager
                          .GetObjectStateEntries(entityState);

            foreach (var objectStateEntry in changes)
            {
                if (objectStateEntry.Entity == null)
                {
                    continue;
                }

                var entityType = objectStateEntry.Entity.GetType();
                entityType = ObjectContext.GetObjectType(entityType);
                if (!Configuration.IsAuditable(entityType))
                {
                    continue;
                }

                var state = new AuditEntryState(ObjectContext, objectStateEntry)
                {
                    AuditLog = auditLog
                };

                if (WriteEntity(state))
                {
                    auditLog.Entities.Add(state.AuditEntity);
                }
            }

            return(auditLog);
        }
コード例 #3
0
        private bool WriteEntity(AuditEntryState state)
        {
            if (state.EntityType == null)
            {
                return(false);
            }

            WriteKeys(state);
            WriteProperties(state);
            WriteRelationships(state);

            return(true);
        }
コード例 #4
0
        private static bool IsLoaded(AuditEntryState state, NavigationProperty navigationProperty,
                                     IMemberAccessor accessor)
        {
            var relationshipManager = state.ObjectStateEntry.RelationshipManager;
            var getEntityReference  = _relatedAccessor.Value.MakeGenericMethod(accessor.MemberType);
            var parameters          = new[]
            {
                navigationProperty.RelationshipType.FullName,
                navigationProperty.ToEndMember.Name
            };

            var entityReference = getEntityReference.Invoke(relationshipManager, parameters) as EntityReference;

            return(entityReference != null && entityReference.IsLoaded);
        }
コード例 #5
0
        private object FormatValue(AuditEntryState state, string name, object value)
        {
            if (value == null)
            {
                return(null);
            }

            var valueType = value.GetType();

            try
            {
                var returnValue = valueType.IsEnum ? Enum.GetName(valueType, value) : value;

                var formatMethod = Configuration.GetFormatter(state.ObjectType, name);
                if (formatMethod == null)
                {
                    return(returnValue);
                }

                var context = new AuditPropertyContext
                {
                    ValueType = valueType,
                    Entity    = state.Entity,
                    Value     = returnValue
                };

                try
                {
                    return(formatMethod.Invoke(null, context));
                }
                catch
                {
                    // eat format error?
                    return(returnValue);
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.Message);
                return(_errorText);
            }
        }
コード例 #6
0
        private static object GetDisplayValue(AuditEntryState state, NavigationProperty navigationProperty,
                                              IMemberAccessor displayMember, DbDataRecord values)
        {
            if (values == null)
            {
                return(null);
            }

            var association = navigationProperty.RelationshipType as AssociationType;

            if (association == null)
            {
                return(null);
            }

            // only support first constraint
            var referentialConstraint = association.ReferentialConstraints.FirstOrDefault();

            if (referentialConstraint == null)
            {
                return(null);
            }

            var toProperties = referentialConstraint
                               .ToProperties
                               .Select(p => p.Name)
                               .ToList();

            var fromProperties = referentialConstraint
                                 .FromProperties
                                 .Select(p => p.Name)
                                 .ToList();

            // make sure key columns match
            if (fromProperties.Count != toProperties.Count)
            {
                return(null);
            }

            var edmType = referentialConstraint
                          .FromProperties
                          .Select(p => p.DeclaringType)
                          .FirstOrDefault();

            if (edmType == null)
            {
                return(null);
            }

            var entitySet = state.ObjectContext.GetEntitySet(edmType.FullName);

            var sql = new StringBuilder();

            sql.Append("SELECT VALUE t.")
            .Append(displayMember.Name)
            .Append(" FROM ")
            .Append(entitySet.Name)
            .Append(" as t")
            .Append(" WHERE ");

            var parameters = new List <ObjectParameter>();

            for (var index = 0; index < fromProperties.Count; index++)
            {
                if (index > 0)
                {
                    sql.Append(" AND ");
                }

                var fromProperty = fromProperties[index];
                var toProperty   = toProperties[index];
                var value        = values.GetValue(toProperty);
                var name         = "@" + fromProperty;

                sql.Append(" t.").Append(fromProperty);
                if (value != null)
                {
                    sql.Append(" == ").Append(name);
                    parameters.Add(new ObjectParameter(fromProperty, value));
                }
                else
                {
                    sql.Append(" is null");
                }
            }

            var q = state.ObjectContext.CreateQuery <object>(
                sql.ToString(),
                parameters.ToArray());

            return(q.FirstOrDefault());
        }
コード例 #7
0
        private void WriteRelationships(AuditEntryState state)
        {
            if (!Configuration.IncludeRelationships)
            {
                return;
            }

            var properties = state.EntityType.NavigationProperties;

            if (properties.Count == 0)
            {
                return;
            }

            var modifiedMembers = state.ObjectStateEntry
                                  .GetModifiedProperties()
                                  .ToList();

            var type = state.ObjectType;

            var currentValues = state.IsDeleted
                ? state.ObjectStateEntry.OriginalValues
                : state.ObjectStateEntry.CurrentValues;

            var originalValues = state.IsModified
                ? state.ObjectStateEntry.OriginalValues
                : null;

            foreach (var navigationProperty in properties)
            {
                if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ||
                    navigationProperty.FromEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many)
                {
                    continue;
                }

                var name = navigationProperty.Name;
                if (Configuration.IsNotAudited(type, name))
                {
                    continue;
                }

                var accessor      = state.EntityAccessor.Find(name);
                var displayMember = Configuration.GetDisplayMember(accessor.MemberType);
                if (displayMember == null)
                {
                    continue; // no display property, skip
                }
                var isModified = IsModifed(navigationProperty, modifiedMembers);

                if (state.IsModified && !isModified &&
                    !Configuration.IsAlwaysAudited(type, name))
                {
                    continue; // this means the property was not changed, skip it
                }
                var isLoaded = IsLoaded(state, navigationProperty, accessor);
                if (!isLoaded && !Configuration.LoadRelationships)
                {
                    continue;
                }

                var auditProperty = new AuditProperty();

                try
                {
                    auditProperty.Name           = name;
                    auditProperty.Type           = accessor.MemberType.FullName;
                    auditProperty.IsRelationship = true;
                    auditProperty.ForeignKey     = GetForeignKey(navigationProperty);

                    object currentValue = null;

                    if (isLoaded)
                    {
                        // get value directly from instance to save db call
                        var valueInstance = accessor.GetValue(state.Entity);
                        if (valueInstance != null)
                        {
                            currentValue = displayMember.GetValue(valueInstance);
                        }
                    }
                    else
                    {
                        // get value from db
                        currentValue = GetDisplayValue(state, navigationProperty, displayMember, currentValues);
                    }

                    // format
                    currentValue = FormatValue(state, name, currentValue);

                    if (!state.IsModified && currentValue == null)
                    {
                        continue; // skip null value
                    }
                    switch (state.AuditEntity.Action)
                    {
                    case AuditAction.Added:
                        auditProperty.Current = currentValue;
                        break;

                    case AuditAction.Modified:
                        auditProperty.Current = currentValue ?? _nullText;

                        if (Configuration.LoadRelationships)
                        {
                            var originalValue = GetDisplayValue(state, navigationProperty, displayMember,
                                                                originalValues);
                            originalValue = FormatValue(state, name, originalValue);

                            auditProperty.Original = originalValue;
                        }

                        break;

                    case AuditAction.Deleted:
                        auditProperty.Original = currentValue;
                        break;
                    }
                }
                catch (Exception ex)
                {
                    Trace.TraceError(ex.Message);
                    if (state.IsDeleted)
                    {
                        auditProperty.Original = _errorText;
                    }
                    else
                    {
                        auditProperty.Current = _errorText;
                    }
                }

                state.AuditEntity.Properties.Add(auditProperty);
            }
        }
コード例 #8
0
        private void WriteProperties(AuditEntryState state)
        {
            var properties = state.EntityType.Properties;

            if (properties == null)
            {
                return;
            }

            var modifiedMembers = state.ObjectStateEntry
                                  .GetModifiedProperties()
                                  .ToList();

            var type = state.ObjectType;

            var currentValues = state.IsDeleted
                ? state.ObjectStateEntry.OriginalValues
                : state.ObjectStateEntry.CurrentValues;

            var originalValues = state.IsModified
                ? state.ObjectStateEntry.OriginalValues
                : null;

            foreach (var edmProperty in properties)
            {
                var name = edmProperty.Name;
                if (Configuration.IsNotAudited(type, name))
                {
                    continue;
                }

                var isModified = modifiedMembers.Any(m => m == name);

                if (state.IsModified && !isModified &&
                    !Configuration.IsAlwaysAudited(type, name))
                {
                    continue; // this means the property was not changed, skip it
                }
                var auditProperty = new AuditProperty();
                try
                {
                    auditProperty.Name = name;
                    auditProperty.Type = GetType(edmProperty);

                    var currentValue = currentValues.GetValue(name);
                    currentValue = FormatValue(state, name, currentValue);

                    if (!state.IsModified && currentValue == null)
                    {
                        continue; // ignore null properties?
                    }
                    switch (state.AuditEntity.Action)
                    {
                    case AuditAction.Added:
                        auditProperty.Current = currentValue;
                        break;

                    case AuditAction.Modified:
                        auditProperty.Current = currentValue;

                        if (originalValues != null)
                        {
                            var originalValue = originalValues.GetValue(edmProperty.Name);
                            originalValue = FormatValue(state, name, originalValue);

                            auditProperty.Original = originalValue;
                        }
                        break;

                    case AuditAction.Deleted:
                        auditProperty.Original = currentValue;
                        break;
                    }
                }
                catch (Exception ex)
                {
                    Trace.TraceError(ex.Message);
                    if (state.IsDeleted)
                    {
                        auditProperty.Original = _errorText;
                    }
                    else
                    {
                        auditProperty.Current = _errorText;
                    }
                }

                state.AuditEntity.Properties.Add(auditProperty);
            } // foreach property
        }