Ejemplo n.º 1
0
        private static void CompleteAudit(DbContext context)
        {
            var entries = context.ChangeTracker.Entries()
                          .Where(x => new[] { EntityState.Added, EntityState.Modified, EntityState.Deleted }.Contains(x.State))
                          .ToArray();
            var predictor = new AuditPredictor();

            var auditEntriesByTypes = entries
                                      .GroupBy(x => x.Entity.GetType())
                                      .Where(x => x.Key.HasAttribute <EntityAuditAttribute>())
                                      .ToArray();

            // Complete EntityAudit
            foreach (var entriesByType in auditEntriesByTypes)
            {
                var attr = entriesByType.Key.GetCustomAttribute <EntityAuditAttribute>();
                foreach (var kv in entriesByType.AsKvPairs())
                {
                    predictor.Add(EntityAudit.Parse(kv.Value));
                }
            }

            foreach (var entriesByType in auditEntriesByTypes)
            {
                var entityType = entriesByType.Key;
                var attr       = entityType.GetCustomAttribute <EntityAuditAttribute>();
                var auditor    = Activator.CreateInstance(attr.EntityAuditorType);
                auditor.GetReflector().DeclaredMethod(nameof(IEntityAuditor <DbContext, object> .OnAudited)).Call(context, predictor);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This method should be called before 'base.SaveChanges'.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="acceptAllChangesOnSuccess"></param>
        /// <returns></returns>
        public static void IntelliTrack(DbContext context, bool acceptAllChangesOnSuccess)
        {
            EntityEntry[] entries;
            IGrouping <Type, EntityEntry>[] auditEntriesByTypes;
            void RefreshEntries()
            {
                entries = context.ChangeTracker.Entries()
                          .Where(x => new[] { EntityState.Added, EntityState.Modified, EntityState.Deleted }.Contains(x.State))
                          .ToArray();
                auditEntriesByTypes = entries
                                      .GroupBy(x => x.Entity.GetType())
                                      .Where(x => x.Key.HasAttribute <EntityAuditAttribute>())
                                      .ToArray();
            }

            var auditorCaches = new CacheContainer <Type, Reflector>
            {
                CacheMethod = auditType => () => Activator.CreateInstance(auditType).GetReflector(),
            };

            RefreshEntries();
            foreach (var entry in entries)
            {
                // Resolve AutoAttributes
                var entity     = entry.Entity;
                var entityType = entity.GetType();
                if (entry.State == EntityState.Added || entry.State == EntityState.Modified)
                {
                    var props = entityType.GetProperties().Where(x => x.CanWrite).ToArray();
                    ResolveAutoAttributes(entry, props);
                }
            }

            // Resolve BeforeAudit
            foreach (var entriesByType in auditEntriesByTypes)
            {
                var entityType = entriesByType.Key;
                var attr       = entityType.GetCustomAttribute <EntityAuditAttribute>();

                var auditType = typeof(EntityAudit <>).MakeGenericType(entityType);
                var audits    = Array.CreateInstance(auditType, entriesByType.Count());
                foreach (var kv in entriesByType.AsKvPairs())
                {
                    audits.SetValue(EntityAudit.Parse(kv.Value), kv.Key);
                }

                auditorCaches[attr.EntityAuditorType].Value
                .DeclaredMethod(nameof(IEntityAuditor <DbContext, object> .BeforeAudit)).Call(context, audits);
            }

            // Resolve OnAuditing
            RefreshEntries();
            foreach (var entriesByType in auditEntriesByTypes)
            {
                var entityType = entriesByType.Key;
                var attr       = entityType.GetCustomAttribute <EntityAuditAttribute>();

                var auditType = typeof(EntityAudit <>).MakeGenericType(entityType);
                var audits    = Array.CreateInstance(auditType, entriesByType.Count());
                foreach (var kv in entriesByType.AsKvPairs())
                {
                    audits.SetValue(EntityAudit.Parse(kv.Value), kv.Key);
                }

                auditorCaches[attr.EntityAuditorType].Value
                .DeclaredMethod(nameof(IEntityAuditor <DbContext, object> .OnAuditing)).Call(context, audits);
            }

            // Resolve OnAudited
            CompleteAudit(context);
        }