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

            return UpdateLog(auditLog);
        }
        /// <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;
        }