예제 #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);

                    object 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);
            }
        }
        /// <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;
            }

            IEnumerable <ObjectStateEntry> changes = ObjectContext
                                                     .ObjectStateManager
                                                     .GetObjectStateEntries(entityState);

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

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

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

                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
파일: AuditLogger.cs 프로젝트: Lietuva2/LT2
        /// <summary>
        /// Creates the <see cref="AuditLog"/> from the current <see cref="ObjectContext"/>.
        /// </summary>
        /// <returns></returns>
        public AuditLog CreateLog()
        {
            var auditLog = new AuditLog
            {
                Date     = DateTime.Now,
                Username = Environment.UserName
            };

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

            IEnumerable <ObjectStateEntry> changes = ObjectContext
                                                     .ObjectStateManager
                                                     .GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified);

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

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

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

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

            return(auditLog);
        }
예제 #6
0
        private object FormatValue(AuditEntryState state, string name, object value)
        {
            if (value == null)
            {
                return(null);
            }

            var valueType = value.GetType();

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

                IMethodAccessor 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, new[] { context }));
                }
                catch
                {
                    // eat format error?
                    return(returnValue);
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.Message);
                return(_errorText);
            }
        }
예제 #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 (NavigationProperty navigationProperty in properties)
            {
                if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ||
                    navigationProperty.FromEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many)
                {
                    continue;
                }

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

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

                if (state.IsModified && !isModified &&
                    !Configuration.IsAlwaysAudited(type, name))
                {
                    continue; // this means the property was not changed, skip it
                }
                bool 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;

                    if (isLoaded)
                    {
                        // get value directly from instance to save db call
                        object valueInstance = accessor.GetValue(state.Entity);
                        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)
                        {
                            object 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);
            }
        }
        /// <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();

	        IEnumerable<ObjectStateEntry> changes = ObjectContext
		        .ObjectStateManager
				.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified)
				.Where(t => !t.IsRelationship);


			foreach (ObjectStateEntry objectStateEntry in ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted).Where(t => t.IsRelationship))
			{
				ObjectStateEntry entryLeft = null;
				ObjectStateEntry entryRight = null;
				var associationEnds = objectStateEntry.GetAssociationEnds();
				NavigationProperty navigationPropertyLeft = objectStateEntry.GetNavigationProperty(associationEnds[0]);
				NavigationProperty navigationPropertyRight = objectStateEntry.GetNavigationProperty(associationEnds[1]);

				if (objectStateEntry.State == EntityState.Added)
				{
					entryLeft = ObjectContext.ObjectStateManager.GetObjectStateEntry((EntityKey)objectStateEntry.CurrentValues[0]);
					entryRight = ObjectContext.ObjectStateManager.GetObjectStateEntry((EntityKey)objectStateEntry.CurrentValues[1]);
				}
				else if (objectStateEntry.State == EntityState.Deleted)
				{
					entryLeft = ObjectContext.ObjectStateManager.GetObjectStateEntry((EntityKey)objectStateEntry.OriginalValues[0]);
					entryRight = ObjectContext.ObjectStateManager.GetObjectStateEntry((EntityKey)objectStateEntry.OriginalValues[1]);
				}

				Type entityTypeLeft = entryLeft.Entity.GetType();
				entityTypeLeft = ObjectContext.GetObjectType(entityTypeLeft);
				if (Configuration.IsAuditable(entityTypeLeft))
				{
					var stateLeft = new AuditEntryState(entryLeft)
					{
						AuditLog = auditLog,
						ObjectContext = ObjectContext,
						AdditionalModifiedProperty = navigationPropertyLeft,
						AdditionalModifiedPropertyEnd = ObjectContext.GetObjectByKey(entryRight.EntityKey),
						AdditionalModifiedPropertyIsAdd = objectStateEntry.State == EntityState.Added
					};

					if (WriteEntity(stateLeft))
						auditLog.Entities.Add(stateLeft.AuditEntity);
				}

				Type entityTypeRight = entryRight.Entity.GetType();
				entityTypeRight = ObjectContext.GetObjectType(entityTypeRight);
				if (Configuration.IsAuditable(entityTypeRight))
				{
					var stateRight = new AuditEntryState(entryRight)
					{
						AuditLog = auditLog,
						ObjectContext = ObjectContext,
						AdditionalModifiedProperty = navigationPropertyRight,
						AdditionalModifiedPropertyEnd = ObjectContext.GetObjectByKey(entryLeft.EntityKey),
						AdditionalModifiedPropertyIsAdd = objectStateEntry.State == EntityState.Added
					};

					if (WriteEntity(stateRight))
						auditLog.Entities.Add(stateRight.AuditEntity);
				}
			}

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

				Type entityType = objectStateEntry.Entity.GetType();

                entityType = ObjectContext.GetObjectType(entityType);
                if (!Configuration.IsAuditable(entityType))
                    continue;

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

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

            return auditLog;
        }
예제 #9
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 (EdmProperty edmProperty in properties)
            {
                string name = edmProperty.Name;
                if (Configuration.IsNotAudited(type, name))
                {
                    continue;
                }

                bool 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)
                        {
                            object 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
        }
        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);
        }
        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 eSql = string.Format("SELECT VALUE t FROM {0} AS t", edmType.Name);

            var q = state.ObjectContext.CreateQuery<object>(eSql);
            for (int index = 0; index < fromProperties.Count; index++)
            {
                string fromProperty = fromProperties[index];
                string toProperty = toProperties[index];

                var value = values.GetValue(toProperty);
                var predicate = string.Format("it.{0} == @{0}", fromProperty);
                var parameter = new ObjectParameter(fromProperty, value);

                q = q.Where(predicate, parameter);
            }
            q = q.SelectValue<object>("it." + displayMember.Name);

            return q.FirstOrDefault();
        }
        private object FormatValue(AuditEntryState state, string name, object value)
        {
            if (value == null)
                return null;

            var valueType = value.GetType();

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

                IMethodAccessor 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, new[] { context });
                }
                catch
                {
                    // eat format error?
                    return returnValue;
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.Message);
                return _errorText;
            }
        }
        /// <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;
            }

            IEnumerable <ObjectStateEntry> changes = ObjectContext
                                                     .ObjectStateManager
                                                     .GetObjectStateEntries(entityState);

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

                Type entityType = objectStateEntry.Entity.GetType();
                entityType = ObjectContext.GetObjectType(entityType);

                //@BaseEAM: Update audit properties in BaseEntity
                var baseEntity = objectStateEntry.Entity as BaseEntity;
                if (baseEntity != null)
                {
                    if (objectStateEntry.State == EntityState.Added)
                    {
                        baseEntity.CreatedDateTime = baseEntity.ModifiedDateTime = Clock.Now;
                        baseEntity.CreatedUser     = baseEntity.ModifiedUser = CurrentUser == null ? "" : CurrentUser.Name;
                    }
                    else if (objectStateEntry.State == EntityState.Modified)
                    {
                        objectStateEntry.SetModifiedProperty("ModifiedDateTime");
                        objectStateEntry.SetModifiedProperty("ModifiedUser");
                        objectStateEntry.SetModifiedProperty("Version");
                        baseEntity.ModifiedDateTime = Clock.Now;
                        baseEntity.ModifiedUser     = CurrentUser == null ? "" : CurrentUser.Name;
                    }

                    // increase version for concurrency checking
                    baseEntity.Version = baseEntity.Version + 1;
                }
                //@BaseEAM
                if (!Configuration.IsAuditable(entityType))
                {
                    continue;
                }

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

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

            return(auditLog);
        }
        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 (EdmProperty edmProperty in properties)
            {
                string name = edmProperty.Name;
                if (Configuration.IsNotAudited(type, name))
                    continue;

                var auditProperty = new AuditProperty();

                try
                {
                    var currentValue = currentValues.GetValue(name);
                    var originalValue = originalValues.GetValue(name);

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

                    if (state.IsModified && !isModified && !Configuration.IsAlwaysAudited(type, name))
                        continue; // this means the property was not changed, skip it

                    auditProperty.Name = name;
                    auditProperty.Type = GetType(edmProperty);

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

                    if ((!state.IsModified && currentValue == null) || (originalValue == null && currentValue == null) || currentValue.Equals(originalValue))
                        continue; // ignore null properties?

                    switch (state.AuditEntity.Action)
                    {
                        case AuditAction.Added:
                            auditProperty.Current = currentValue;
                            break;
                        case AuditAction.Modified:
                            auditProperty.Current = currentValue;

                            if (originalValues != null)
                            {
                                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

        }
예제 #15
0
파일: AuditLogger.cs 프로젝트: Lietuva2/LT2
        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 eSql = string.Format("SELECT VALUE t FROM {0} AS t", edmType.Name);

            var q = state.ObjectContext.CreateQuery <object>(eSql);

            for (int index = 0; index < fromProperties.Count; index++)
            {
                string fromProperty = fromProperties[index];
                string toProperty   = toProperties[index];

                var value     = values.GetValue(toProperty);
                var predicate = string.Format("it.{0} == @{0}", fromProperty);
                var parameter = new ObjectParameter(fromProperty, value);

                q = q.Where(predicate, parameter);
            }
            q = q.SelectValue <object>("it." + displayMember.Name);

            return(q.FirstOrDefault());
        }
        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);

                    object 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);
            }
        }
        private bool WriteEntity(AuditEntryState state)
        {
            if (state.EntityType == null)
                return false;

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

            return true;
        }
        /// <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;

            IEnumerable<ObjectStateEntry> changes = ObjectContext
                .ObjectStateManager
                .GetObjectStateEntries(entityState);

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

                Type 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;
        }
예제 #19
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 (int index = 0; index < fromProperties.Count; index++)
            {
                if (parameters.Count > 1)
                {
                    sql.Append(" AND ");
                }

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

                sql.Append(" t.")
                .Append(fromProperty)
                .Append(" == ")
                .Append(name);

                parameters.Add(new ObjectParameter(fromProperty, value));
            }

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

            return(q.FirstOrDefault());
        }
        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 (int index = 0; index < fromProperties.Count; index++)
            {
                if (index > 0)
                    sql.Append(" AND ");

                string fromProperty = fromProperties[index];
                string 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();
        }
        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 (NavigationProperty navigationProperty in properties)
            {
                if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many
                    || navigationProperty.FromEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many)
                    continue;

                string name = navigationProperty.Name;
                if (Configuration.IsNotAudited(type, name))
                    continue;

                var accessor = state.EntityAccessor.Find(name);
                IMemberAccessor displayMember = Configuration.GetDisplayMember(accessor.MemberType);
                if (displayMember == null)
                    continue; // no display property, skip

                bool isModified = IsModifed(navigationProperty, modifiedMembers);

                if (state.IsModified && !isModified
                  && !Configuration.IsAlwaysAudited(type, name))
                    continue; // this means the property was not changed, skip it

                bool 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
                        object 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)
                            {
                                object 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);
            }
        }
        /// <summary>
        /// Creates the <see cref="AuditLog"/> from the current <see cref="ObjectContext"/>.
        /// </summary>
        /// <returns></returns>
        public AuditLog CreateLog()
        {
            var auditLog = new AuditLog
            {
                Date = DateTime.Now,
                Username = Environment.UserName
            };

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

            IEnumerable<ObjectStateEntry> changes = ObjectContext
              .ObjectStateManager
              .GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified);

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

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

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

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

            return auditLog;
        }