/// <summary>
        /// To return the formatted list of IAuditLog entity.
        /// </summary>
        /// <param name="entityEntry"></param>
        /// <param name="userId"></param>
        /// <param name="loginSessionId"></param>
        /// <param name="entityState"></param>
        /// <returns></returns>
        private IEnumerable <IAuditLog> GenerateChangeLogs(EntityEntry entityEntry,
                                                           string userId,
                                                           EntityState entityState)
        {
            var returnValue = new List <IAuditLog>();

            // Collecting primary key value and name of a single entity entry
            var keyRepresentation = GetPrimaryKeyInfo(entityEntry, KeySeperator);

            // Collecting properties of the single entity entry.
            var auditedPropertyNames = entityEntry.Entity.GetType().GetProperties().Select(info => info.Name).ToList();

            // Collecting all the pre-defined non-auditable properties.
            var nonAuditablePropertyNames = Enum.GetValues(typeof(NonAuditableAttribute)).Cast <NonAuditableAttribute>().Select(v => v.ToString()).ToList();

            // Removing non-auditable properties.
            auditedPropertyNames = auditedPropertyNames.Where(x => !nonAuditablePropertyNames.Contains(x)).ToList();

            // Looping each properties of the single entity entry
            foreach (var propertyEntry in entityEntry.Metadata.GetProperties().Where(x => auditedPropertyNames.Contains(x.Name)).Select(property => entityEntry.Property(property.Name)))
            {
                var originalValue = Convert.ToString(entityEntry.GetDatabaseValues().GetValue <object>(propertyEntry.Metadata.Name));

                // Current value will be empty for delete opeations
                if (entityState == EntityState.Modified)
                {
                    string currentValue = null;
                    if (propertyEntry.CurrentValue != null)
                    {
                        // Collecting current value
                        currentValue = Convert.ToString(propertyEntry.CurrentValue);
                    }

                    // Skip : If original value and old value are same
                    if (originalValue.Equals(currentValue))
                    {
                        continue;
                    }
                }
                returnValue.Add(new AuditLog
                {
                    PrimaryKeyNames  = keyRepresentation.Key,
                    PrimaryKeyValues = keyRepresentation.Value,
                    OriginalValue    = entityState != EntityState.Added ? Convert.ToString(originalValue) : null,
                    NewValue         = entityState == EntityState.Modified || entityState == EntityState.Added ? Convert.ToString(propertyEntry.CurrentValue) : null,
                    PropertyName     = propertyEntry.Metadata.Name,
                    TimeStamp        = DateTime.UtcNow,
                    EventType        = entityState.ToString(),
                    UserId           = userId,
                    TableName        = entityEntry.Entity.GetType().Name,
                });
            }

            return(returnValue);
        }
        public async Task <ActionResult> AddProjects(int brandId)
        {
            int retryCount = 0;

            var projectDetails = new TrProjectDetails()
            {
                BrandId  = brandId,
                IsActive = true
            };

            context.TrProjectDetails.Add(projectDetails);

            while (retryCount < 3)
            {
                try
                {
                    var sequenceIdDetails = await context.TrProjectSequenceMapper.FirstOrDefaultAsync(i => i.IsActive && i.BrandId == brandId)
                                            .ConfigureAwait(false);

                    projectDetails.BrandProjectId = sequenceIdDetails.SequenceId;
                    sequenceIdDetails.SequenceId++;

                    if (retryCount == 0)
                    {
                        var sequenceId = new SqlParameter("sequenceId", sequenceIdDetails.SequenceId);
                        var dbBrandId  = new SqlParameter("brandId", brandId);
                        context.Database.ExecuteSqlRaw("UPDATE TR_ProjectSequenceMapper SET SequenceId = @sequenceId WHERE BrandId = @brandId", dbBrandId, sequenceId);
                    }

                    await context.SaveChangesAsync().ConfigureAwait(false);

                    var projectIdMapperDetails = new TrProjectMapper()
                    {
                        ProjectId = projectDetails.Id,
                        IsActive  = true
                    };

                    await context.TrProjectMapper.AddAsync(projectIdMapperDetails).ConfigureAwait(false);

                    await context.SaveChangesAsync().ConfigureAwait(false);


                    retryCount = 3;
                }
                catch (DbUpdateConcurrencyException ex)
                {
                    retryCount++;
                    EntityEntry exceptionEntry = ex.Entries.Single();
                    var         databaseEntry  = exceptionEntry.GetDatabaseValues();
                    exceptionEntry.OriginalValues.SetValues(databaseEntry);
                }
            }

            return(new JsonResult(new { result = projectDetails.BrandProjectId }));
        }
        internal HistoryChanges CreateHistoryChanges(EntityEntry entry)
        {
            var history = new HistoryChanges
            {
                TableName = entry.Metadata.Relational().TableName
            };

            var jsonSerializer = new JsonSerializer();

            var json = new JObject();

            var bef = new JObject();
            var aft = new JObject();

            foreach (var prop in entry.Properties)
            {
                if (prop.IsModified)
                {
                    if (prop.OriginalValue != null)
                    {
                        if (prop.OriginalValue != prop.CurrentValue)
                        {
                            bef[prop.Metadata.Name] = JToken.FromObject(prop.OriginalValue, jsonSerializer);
                        }
                        else
                        {
                            var originalValue = entry.GetDatabaseValues().GetValue <object>(prop.Metadata.Name);
                            bef[prop.Metadata.Name] = originalValue != null
                                ? JToken.FromObject(originalValue, jsonSerializer)
                                : JValue.CreateNull();
                        }
                    }
                    else
                    {
                        bef[prop.Metadata.Name] = JValue.CreateNull();
                    }

                    aft[prop.Metadata.Name] = prop.CurrentValue != null
                        ? JToken.FromObject(prop.CurrentValue, jsonSerializer)
                        : JValue.CreateNull();
                }
            }

            json["before"] = bef;
            json["after"]  = aft;

            history.RowId       = PrimaryKey(entry);
            history.EntityState = EntityState.Modified;
            history.Change      = json.ToString(Formatting.None);

            return(history);
        }
Example #4
0
        /// <summary>
        /// Herhangi bir entity için onun önceki durumunu getirir.
        /// </summary>
        /// <param name="entry">ChangeTracker üzerinden elde edilen her bir EntityEntry değerini tanımlamaktadır</param>
        /// <returns></returns>

        private object GetOldValues(EntityEntry entry)
        {
            var entityType = entry.Entity.GetType();
            var entity     = Activator.CreateInstance(entityType);

            foreach (var prop in entry.Properties)
            {
                var propertyValue  = entry.GetDatabaseValues().GetValue <object>(prop.Metadata.Name);
                var entityProperty = entityType.GetProperty(prop.Metadata.Name);
                entityProperty.SetValue(entity, propertyValue);
            }
            return(entity);
        }
Example #5
0
        public void Modify(TEntity entity, Include <TEntity> include = null)
        {
            auditVisitor.SetAuditProperties(entity);
            EntityEntry <TEntity> entry = context.Entry(entity);

            // alternative: context.Entry(entity).Property("GroupAdName").IsModified = false;
            if (include != null)
            {
                var propertyValues = entry.GetDatabaseValues();
                var entityDbState  = (TEntity)propertyValues.ToObject();
                ObjectExtensions.Copy(entityDbState, entity, include);
            }
            entry.State = EntityState.Modified;
        }
        private TReport AddModifiedReport <TReport>(EntityEntry entry) where TReport : Report, new()
        {
            var report = new TReport();

            report.TableName = entry.Metadata.Relational().TableName;

            var properties = entry.Properties;

            var json = new JObject();
            var bef  = new JObject();
            var aft  = new JObject();

            foreach (var prop in properties)
            {
                if (prop.IsModified)
                {
                    if (prop.OriginalValue != null)
                    {
                        if (prop.OriginalValue != prop.CurrentValue)
                        {
                            bef[prop.Metadata.Name] = JToken.FromObject(prop.OriginalValue);
                        }
                        else
                        {
                            var originalValue = entry.GetDatabaseValues().GetValue <object>(prop.Metadata.Name);
                            bef[prop.Metadata.Name] = originalValue != null
                                ? JToken.FromObject(originalValue)
                                : JValue.CreateNull();
                        }
                    }
                    else
                    {
                        bef[prop.Metadata.Name] = JValue.CreateNull();
                    }

                    aft[prop.Metadata.Name] = prop.CurrentValue != null
                    ? JToken.FromObject(prop.CurrentValue)
                    : JValue.CreateNull();
                }
            }

            json["before"] = bef;
            json["after"]  = aft;

            report.RowId       = this.PrimaryKey(entry);
            report.EntityState = EntityState.Modified;
            report.Changed     = json.ToString(_eFCoreChangeReportConfiguration.JsonSerializerSettings.Formatting);

            return(report);
        }
        protected virtual object OriginalValue(string propertyName)
        {
            object originalValue = null;

            if (GlobalTrackingConfig.DisconnectedContext)
            {
                originalValue = _dbEntry.GetDatabaseValues().GetValue <object>(propertyName);
            }
            else
            {
                originalValue = _dbEntry.Property(propertyName).OriginalValue;
            }

            return(originalValue);
        }
Example #8
0
        public LoggableEntity(EntityEntry <BaseModel> entry)
        {
            PropertyValues values =
                entry.State == EntityState.Modified || entry.State == EntityState.Deleted
                    ? entry.GetDatabaseValues()
                    : entry.CurrentValues;

            Properties = values.Properties.Where(property => property.Name != IdName).Select(property => new LoggableProperty(entry.Property(property.Name), values[property]));
            Properties = entry.State == EntityState.Modified ? Properties.Where(property => property.IsModified) : Properties;
            Properties = Properties.ToArray();

            Name   = entry.Entity.GetType().Name;
            Action = entry.State.ToString();
            Id     = () => entry.Entity.Id;
        }
Example #9
0
        private LogEntity LogModifiedEntity(EntityEntry entityEntry)
        {
            var databaseValues           = entityEntry.GetDatabaseValues();
            var modifiedEntityProperties = entityEntry.OriginalValues
                                           .Properties
                                           .Where(p =>
            {
                var originalValue = (databaseValues[p.Name] ?? string.Empty).ToString();
                var currentValue  = (entityEntry.CurrentValues[p.Name] ?? string.Empty).ToString();

                return(entityEntry.Property(p.Name).IsModified&& originalValue != currentValue);
            })
                                           .Select(p => new ModifiedEntityProperty
            {
                PropertyName = p.Name,
                OldValue     = (databaseValues[p.Name] ?? string.Empty).ToString(),
                NewValue     = (entityEntry.CurrentValues[p.Name] ?? string.Empty).ToString()
            })
                                           .ToList();
            var logEntity = new LogEntity
            {
                EntityName     = entityEntry.Entity.GetType().Name,
                EntityFullName = entityEntry.Entity.GetType().FullName,
                EntityAssembly = entityEntry.Entity.GetType().Assembly.GetName().Name,
                LogActionType  = LogActionType.Update,
                OriginalValues = JsonConvert.SerializeObject(entityEntry.GetDatabaseValues().ToObject(), new JsonSerializerSettings
                {
                    ContractResolver = new SimpleTypeContractResolver()
                }),
                ChangedValues = JsonConvert.SerializeObject(modifiedEntityProperties),
                CreatedAt     = DateTime.Now,
                TransactionId = Database.CurrentTransaction.TransactionId.ToString()
            };

            return(logEntity);
        }
Example #10
0
        private void GetDeletedProperties(EntityEntry entry, XmlElement tableNode, XmlDocument doc)
        {
            PropertyValues dbValues = entry.GetDatabaseValues();

            foreach (var propertyName in dbValues.Properties)
            {
                var oldVal = dbValues[propertyName];
                if (oldVal != null)
                {
                    XmlElement propertyNode = doc.CreateElement(propertyName.Name);
                    propertyNode.SetAttribute("DeletedValue", oldVal.ToString());
                    tableNode.AppendChild(propertyNode);
                }
            }
        }
Example #11
0
        internal static Dictionary <string, object> GetChangedProperties <T>(this EntityEntry <T> entry) where T : class
        {
            if (entry.Context.IsNewEntry(entry.Entity))
            {
                var keyProperties = GetKeys(entry);
                return(entry.Properties.Where(x => !keyProperties.Contains(x.Metadata)).ToDictionary(k => k.Metadata.Name, v => v.CurrentValue));
            }

            var dbData = entry.GetDatabaseValues();

            return(entry.Properties.Where(
                       x => x.Metadata.Name != "Discriminator" && //TODO: Maybe check for ShadowProperties?
                       ((entry.CurrentValues[x.Metadata.Name] == null && dbData[x.Metadata.Name] != null) ||
                        (entry.CurrentValues[x.Metadata.Name] != null && !entry.CurrentValues[x.Metadata.Name].Equals(dbData[x.Metadata.Name]))
                       )).ToDictionary(k => k.Metadata.Name, v => entry.CurrentValues[v.Metadata.Name]));
        }
Example #12
0
        private void SetModifiedProperties(EntityEntry entry, out string oldData, out string newData)
        {
            string json = string.Empty;
            List <AuditEntityProperties> auditEntitiesmodel = new List <AuditEntityProperties>();

            try
            {
                PropertyValues dbValues = entry.GetDatabaseValues();
                foreach (var propertyName in entry.OriginalValues.Properties)
                {
                    var oldVal = dbValues[propertyName.Name];
                    //to get dbValue
                    if (oldVal != null)
                    {
                        if (json.Length > 0)
                        {
                            json += ", ";
                        }
                        json += $@"""{propertyName}"":{(oldVal == null ? "null" : (IsNumber(oldVal) ? oldVal.ToString() : $@"""{oldVal.ToString().Replace("\"", "'")}"""))}";
                    }
                    //to get modified values
                    if (propertyName.Name != "RowVersion")
                    {
                        var newVal = entry.CurrentValues[propertyName];
                        if (oldVal != null && newVal != null && !Equals(oldVal, newVal))
                        {
                            AuditEntityProperties singleauditEntitymodel = new AuditEntityProperties();
                            singleauditEntitymodel.PropertyName = propertyName.Name;
                            singleauditEntitymodel.OldValue     = oldVal.ToString();
                            singleauditEntitymodel.NewValue     = newVal.ToString();
                            auditEntitiesmodel.Add(singleauditEntitymodel);
                        }
                    }
                }
                oldData = $"{{ {json} }}";
                newData = JsonConvert.SerializeObject(auditEntitiesmodel, Formatting.Indented,
                                                      new JsonSerializerSettings()
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                });
            }
            catch
            {
                oldData = $"{{ {json} }}";
                newData = string.Empty;
            }
        }
 static void Main(string[] args)
 {
     SetupDatabase();
     using (var db = new BloggingContext())
     {
         var blog = new Blog {
             Name = "Skimedic's Blog", Url = "http://skimedic.com"
         };
         var blog2 = new Blog {
             Name = "Brandon's Blog", Url = "http://thirtywaytodropdatabases.com"
         };
         db.Add(blog);
         db.Add(blog2);
         db.SaveChanges();
         //change values outside of current context
         db.Database.ExecuteSqlInterpolated($"Update dbo.blogs set name='Foo' where BlogId = {blog.BlogId}");
         blog.Name  = "Bar";
         blog2.Name = "Brandon's retired and digging ditches now";
         try
         {
             db.SaveChanges();
         }
         catch (DbUpdateConcurrencyException ex)
         {
             Console.WriteLine(ex.Message);
             EntityEntry entryEntity = ex.Entries[0];
             //Kept in DbChangeTracker
             PropertyValues originalValues = entryEntity.OriginalValues;
             PropertyValues currentValues  = entryEntity.CurrentValues;
             IEnumerable <PropertyEntry> modifiedEntries =
                 entryEntity.Properties.Where(e => e.IsModified);
             foreach (var itm in modifiedEntries)
             {
                 //Console.WriteLine($"{itm.Metadata.Name},");
             }
             //Needs to call to database to get values
             PropertyValues databaseValues = entryEntity.GetDatabaseValues();
             //Discards local changes, gets database values, resets change tracker
             entryEntity.Reload();
             //logging stuff here
             //throw new AppDbUpdateException(ex,IList<Customer>)
         }
     }
     Console.WriteLine("Press any key to continue");
     Console.ReadKey();
 }
Example #14
0
        private void GetModifiedProperties(EntityEntry entry, XmlElement tableNode, XmlDocument doc)
        {
            PropertyValues dbValues = entry.GetDatabaseValues();

            foreach (var propertyName in entry.OriginalValues.Properties)
            {
                var oldVal = dbValues[propertyName];
                var newVal = entry.CurrentValues[propertyName];
                if (oldVal != null && newVal != null && !Equals(oldVal, newVal))
                {
                    XmlElement propertyNode = doc.CreateElement(propertyName.Name);
                    propertyNode.SetAttribute("NewValue", newVal.ToString());
                    propertyNode.SetAttribute("OldValue", oldVal.ToString());
                    tableNode.AppendChild(propertyNode);
                }
            }
        }
Example #15
0
        public LoggableEntity(EntityEntry <AModel> entry)
        {
            Type           type   = entry.Entity.GetType();
            PropertyValues values = entry.State == EntityState.Modified || entry.State == EntityState.Deleted
                ? entry.GetDatabaseValues()
                : entry.CurrentValues;

            Properties = values
                         .Properties
                         .Where(property => property.Name != IdName)
                         .Select(property => new LoggableProperty(entry.Property(property.Name), values[property]))
                         .Where(property => entry.State != EntityState.Modified || property.IsModified)
                         .ToArray();

            Name       = type.AssemblyQualifiedName?.StartsWith("Castle.Proxies") == true ? type.BaseType !.Name : type.Name;
            IsModified = Properties.Length > 0;
            Action     = entry.State.ToString();
            Id         = () => entry.Entity.Id;
        }
        private static void WriteHistoryModifiedState(AutoHistory history, EntityEntry entry, IEnumerable <PropertyEntry> properties)
        {
            dynamic json = new System.Dynamic.ExpandoObject();
            dynamic bef  = new System.Dynamic.ExpandoObject();
            dynamic aft  = new System.Dynamic.ExpandoObject();

            PropertyValues databaseValues = null;

            foreach (var prop in properties)
            {
                if (prop.IsModified)
                {
                    if (prop.OriginalValue != null)
                    {
                        if (!prop.OriginalValue.Equals(prop.CurrentValue))
                        {
                            ((IDictionary <String, Object>)bef)[prop.Metadata.Name] = prop.OriginalValue;
                        }
                        else
                        {
                            databaseValues ??= entry.GetDatabaseValues();
                            var originalValue = databaseValues.GetValue <object>(prop.Metadata.Name);
                            ((IDictionary <String, Object>)bef)[prop.Metadata.Name] = originalValue;
                        }
                    }
                    else
                    {
                        ((IDictionary <String, Object>)bef)[prop.Metadata.Name] = null;
                    }

                    ((IDictionary <String, Object>)aft)[prop.Metadata.Name] = prop.CurrentValue;
                }
            }

            ((IDictionary <String, Object>)json)["before"] = bef;
            ((IDictionary <String, Object>)json)["after"]  = aft;

            history.RowId   = entry.PrimaryKey();
            history.Kind    = EntityState.Modified;
            history.Changed = JsonSerializer.Serialize(json, AutoHistoryOptions.Instance.JsonSerializerOptions);
        }
 static void Main(string[] args)
 {
     SetupDatabase();
     using (var db = new BloggingContext())
     {
         var blog = new Blog {
             Name = "saikiran's Blog", Url = "http://www.saikiranpotru.blogspot.com"
         };
         db.Add(blog);
         db.SaveChanges();
         //change values outside of current context
         db.Database.ExecuteSqlCommand($"Update dbo.blogs set name='Foo' where {nameof(Blog.BlogId)} = {blog.BlogId}");
         blog.Name = "Bar";
         try
         {
             db.SaveChanges();
         }
         catch (DbUpdateConcurrencyException ex)
         {
             Console.WriteLine(ex.Message);
             EntityEntry entryEntity = ex.Entries[0];
             //Kept in DbChangeTracker
             PropertyValues originalValues = entryEntity.OriginalValues;
             PropertyValues currentValues  = entryEntity.CurrentValues;
             IEnumerable <PropertyEntry> modifiedEntries = entryEntity.Properties.Where(e => e.IsModified);
             foreach (var itm in modifiedEntries)
             {
                 //Console.WriteLine($"{itm.Metadata.Name},");
             }
             //Needs to call to database to get values
             PropertyValues databaseValues = entryEntity.GetDatabaseValues();
             //Discards local changes, gets database values, resets change tracker
             entryEntity.Reload();
         }
     }
     Console.WriteLine("Press any key to continue");
     Console.ReadKey();
 }
Example #18
0
        public static EntityEntry Refresh(this EntityEntry tracking,
                                          RefreshConflict refreshMode)
        {
            switch (refreshMode)
            {
            case RefreshConflict.StoreWins:
            {
                //当实体被删除时,重新加载设置追踪状态为Detached
                //当实体被更新时,重新加载设置追踪状态为Unchanged
                tracking.Reload();
                break;
            }

            case RefreshConflict.ClientWins:
            {
                PropertyValues databaseValues = tracking.GetDatabaseValues();
                if (databaseValues == null)
                {
                    //当实体被删除时,设置追踪状态为Detached,当然此时客户端无所谓获胜
                    tracking.State = EntityState.Detached;
                }
                else
                {
                    //当实体被更新时,刷新数据库原始值
                    tracking.OriginalValues.SetValues(databaseValues);
                }
                break;
            }

            case RefreshConflict.MergeClientAndStore:
            {
                PropertyValues databaseValues = tracking.GetDatabaseValues();
                if (databaseValues == null)
                {
                    /*当实体被删除时,设置追踪状态为Detached,当然此时客户端没有合并的数据
                     * 并设置追踪状态为Detached
                     */
                    tracking.State = EntityState.Detached;
                }
                else
                {
                    //当实体被更新时,刷新数据库原始值
                    PropertyValues originalValues = tracking.OriginalValues.Clone();
                    tracking.OriginalValues.SetValues(databaseValues);
                    //如果数据库中对于属性有不同的值保留数据库中的值
#if SelfDefine
                    databaseValues.PropertyNames // Navigation properties are not included.
                    .Where(property => !object.Equals(originalValues[property], databaseValues[property]))
                    .ForEach(property => tracking.Property(property).IsModified = false);
#else
                    databaseValues.Properties
                    .Where(property => !object.Equals(originalValues[property.Name],
                                                      databaseValues[property.Name]))
                    .ToList()
                    .ForEach(property =>
                             tracking.Property(property.Name).IsModified = false);
#endif
                }
                break;
            }
            }
            return(tracking);
        }
        internal static TAutoHistory AutoHistory <TAutoHistory>(this EntityEntry entry, Func <TAutoHistory> createHistoryFactory)
            where TAutoHistory : AutoHistory
        {
            var history = createHistoryFactory();

            history.TableName = entry.Metadata.GetTableName();

            // Get the mapped properties for the entity type.
            // (include shadow properties, not include navigations & references)
            var properties = entry.Properties;

            var formatting     = AutoHistoryOptions.Instance.JsonSerializerSettings.Formatting;
            var jsonSerializer = AutoHistoryOptions.Instance.JsonSerializer;
            var json           = new JObject();

            switch (entry.State)
            {
            case EntityState.Added:
                foreach (var prop in properties)
                {
                    if (prop.Metadata.IsKey() || prop.Metadata.IsForeignKey())
                    {
                        continue;
                    }
                    json[prop.Metadata.Name] = prop.CurrentValue != null
                            ? JToken.FromObject(prop.CurrentValue, jsonSerializer)
                            : JValue.CreateNull();
                }

                // REVIEW: what's the best way to set the RowId?
                history.RowId   = "0";
                history.Kind    = EntityState.Added;
                history.Changed = json.ToString(formatting);
                break;

            case EntityState.Modified:
                var bef = new JObject();
                var aft = new JObject();

                foreach (var prop in properties)
                {
                    if (prop.IsModified)
                    {
                        if (prop.OriginalValue != null)
                        {
                            if (prop.OriginalValue != prop.CurrentValue)
                            {
                                bef[prop.Metadata.Name] = JToken.FromObject(prop.OriginalValue, jsonSerializer);
                            }
                            else
                            {
                                var originalValue = entry.GetDatabaseValues().GetValue <object>(prop.Metadata.Name);
                                bef[prop.Metadata.Name] = originalValue != null
                                        ? JToken.FromObject(originalValue, jsonSerializer)
                                        : JValue.CreateNull();
                            }
                        }
                        else
                        {
                            bef[prop.Metadata.Name] = JValue.CreateNull();
                        }

                        aft[prop.Metadata.Name] = prop.CurrentValue != null
                            ? JToken.FromObject(prop.CurrentValue, jsonSerializer)
                            : JValue.CreateNull();
                    }
                }

                json["before"] = bef;
                json["after"]  = aft;

                history.RowId   = entry.PrimaryKey();
                history.Kind    = EntityState.Modified;
                history.Changed = json.ToString(formatting);
                break;

            case EntityState.Deleted:
                foreach (var prop in properties)
                {
                    json[prop.Metadata.Name] = prop.OriginalValue != null
                            ? JToken.FromObject(prop.OriginalValue, jsonSerializer)
                            : JValue.CreateNull();
                }
                history.RowId   = entry.PrimaryKey();
                history.Kind    = EntityState.Deleted;
                history.Changed = json.ToString(formatting);
                break;

            case EntityState.Detached:
            case EntityState.Unchanged:
            default:
                throw new NotSupportedException("AutoHistory only support Deleted and Modified entity.");
            }

            return(history);
        }
        public void LoggableEntity_CreatesPropertiesForDeletedEntity()
        {
            entry.State = EntityState.Deleted;

            AsssertProperties(entry.GetDatabaseValues());
        }
Example #21
0
        public void Log <K>(EntityEntry <T> entityEntry, int?parentEntityId = null, int?relatedEntityId = null) where K : class, ILog
        {
            if (entityEntry.Entity.Deleted)
            {
                entityEntry.State = EntityState.Deleted;
            }
            DbSet <K> _loggerDbSet = _context.Set <K>();

            if (entityEntry.State == EntityState.Modified)
            {
                var entryProperties = entityEntry.Properties.Where(x =>
                                                                   x.Metadata.Name != nameof(entityEntry.Entity.CreatedBy) &&
                                                                   x.Metadata.Name != nameof(entityEntry.Entity.CreatedDate) &&
                                                                   x.Metadata.Name != nameof(entityEntry.Entity.UpdatedBy) &&
                                                                   x.Metadata.Name != nameof(entityEntry.Entity.UpdatedDate));
                foreach (var entry in entryProperties)
                {
                    var propertyName  = entry.Metadata.Name;
                    var originalValue = entityEntry.GetDatabaseValues().GetValue <object>(propertyName)?.ToString();
                    var currentValue  = entry.CurrentValue?.ToString();
                    if (originalValue != currentValue)
                    {
                        Type type           = entry.EntityEntry.Metadata.FindProperty(propertyName).ClrType;
                        Type underlyingType = Nullable.GetUnderlyingType(type);
                        bool isEnum         = underlyingType?.IsEnum ?? false;

                        string mappedOriginalValue = originalValue;
                        string mappedCurrentValue  = currentValue;


                        if (entry.Metadata.IsForeignKey())
                        {
                            var entityFullName    = entityEntry.Entity.GetType().FullName;
                            var relatedEntityType = _context.Model.GetEntityTypes().FirstOrDefault(x => x.Name == entityFullName)
                                                    .GetNavigations().FirstOrDefault(x => x.ForeignKey.Properties.FirstOrDefault().Name == propertyName).ClrType;
                            if (relatedEntityType != null)
                            {
                                var relatedEntityDbSet    = (IQueryable <IBaseEntity>)_context.GetType().GetMethod("Set").MakeGenericMethod(relatedEntityType).Invoke(_context, null);
                                var originalRelatedEntity = (relatedEntityDbSet.FirstOrDefault(X => X.Id == Convert.ToInt32(originalValue)) as object);
                                var currentRelatedEntity  = (relatedEntityDbSet.FirstOrDefault(X => X.Id == Convert.ToInt32(currentValue)) as object);
                                if (originalRelatedEntity?.GetType().GetProperty("Name") != null)
                                {
                                    mappedOriginalValue = (originalRelatedEntity as dynamic).Name;
                                }
                                else if (originalRelatedEntity?.GetType().GetProperty("DisplayName") != null)
                                {
                                    mappedOriginalValue = (originalRelatedEntity as dynamic).DisplayName;
                                }

                                if (currentRelatedEntity?.GetType().GetProperty("Name") != null)
                                {
                                    mappedCurrentValue = (currentRelatedEntity as dynamic).Name;
                                }
                                else if (currentRelatedEntity?.GetType().GetProperty("DisplayName") != null)
                                {
                                    mappedCurrentValue = (currentRelatedEntity as dynamic).DisplayName;
                                }
                            }
                        }

                        K log = Activator.CreateInstance <K>();
                        log.EntityId            = entityEntry.Entity.Id;
                        log.EntityState         = entityEntry.State;
                        log.EntityName          = entityEntry.Entity.GetType().GetDescription();
                        log.PropertyName        = entry.Metadata.PropertyInfo.GetDescription();
                        log.OriginalValue       = originalValue;
                        log.CurrentValue        = currentValue;
                        log.MappedOriginalValue = mappedOriginalValue;
                        log.MappedCurrentValue  = mappedCurrentValue;
                        log.ParentEntityId      = parentEntityId;
                        log.RelatedEntityId     = relatedEntityId;
                        _loggerDbSet.Add(log);
                    }
                }
            }
            else
            {
                K log = Activator.CreateInstance <K>();
                log.EntityId            = entityEntry.Entity.Id;
                log.EntityState         = entityEntry.State;
                log.EntityName          = entityEntry.Entity.GetType().GetDescription();
                log.PropertyName        = null;
                log.OriginalValue       = null;
                log.CurrentValue        = null;
                log.MappedOriginalValue = null;
                log.MappedCurrentValue  = null;
                log.ParentEntityId      = parentEntityId;
                log.RelatedEntityId     = relatedEntityId;
                _loggerDbSet.Add(log);
            }
        }
        private List <AuditLogs> GetModifiedProperties(EntityEntry entry, string screenName, string action, Nullable <int> patientId, Nullable <int> userId, string parentInfo, TokenModel token)
        {
            List <AuditLogs> auditInfoList = new List <AuditLogs>();
            string           TableName     = GetTableName(entry);

            string[] entityName = TableName.Split('_');
            if (entityName.Count() == 2)
            {
                TableName = entityName[0];
            }
            PropertyValues dbValues = entry.GetDatabaseValues();

            foreach (var property in entry.OriginalValues.Properties)
            {
                string    newVal    = Convert.ToString(entry.CurrentValues[property]).Trim();
                string    oldVal    = Convert.ToString(dbValues[property]).Trim();
                AuditLogs auditInfo = new AuditLogs();
                if (oldVal != null && !oldVal.Equals(newVal))
                {
                    int    TableId  = _context.AuditLogTable.Where(p => p.TableName == TableName && p.IsActive == true && p.OrganizationID == token.OrganizationID).Select(p => p.Id).FirstOrDefault();
                    var    ColumnId = _context.AuditLogColumn.Where(p => p.AuditLogTableId == TableId && p.ColumnName == property.Name && p.IsActive == true).Select(p => p.Id).FirstOrDefault();
                    string query    = _context.AuditLogColumn.Where(p => p.AuditLogTableId == TableId && p.ColumnName == property.Name && p.IsActive == true).Select(p => p.Query).FirstOrDefault();
                    if (ColumnId != 0)
                    {
                        auditInfo.PatientId        = patientId;
                        auditInfo.AuditLogColumnId = ColumnId;
                        auditInfo.ScreenName       = screenName;
                        auditInfo.CreatedDate      = DateTime.UtcNow; // UTC Time for manage Time according to time zone
                        auditInfo.CreatedById      = userId;
                        auditInfo.Action           = action;
                        auditInfo.ParentInfo       = parentInfo;
                        if (!string.IsNullOrEmpty(query))
                        {
                            GetForeignTableData dt = null;
                            int  n;
                            bool isNumeric = int.TryParse(Convert.ToString(entry.CurrentValues[property]), out n);
                            if (entry.CurrentValues[property] != null)
                            {
                                dt = _context.ExecuteQuery <GetForeignTableData>(query.Replace("@Id", isNumeric == true ? Convert.ToString(entry.CurrentValues[property]) : "'" + Convert.ToString(entry.CurrentValues[property]) + "'"), 0).FirstOrDefault();
                                if (dt != null)
                                {
                                    auditInfo.NewValue = Convert.ToString(dt.Value);
                                }
                            }
                            else
                            {
                                auditInfo.NewValue = null;
                            }

                            isNumeric = int.TryParse(Convert.ToString(dbValues[property]), out n);
                            if (dbValues[property] != null)
                            {
                                dt = _context.ExecuteQuery <GetForeignTableData>(query.Replace("@Id", isNumeric == true ? Convert.ToString(dbValues[property]) : "'" + Convert.ToString(dbValues[property]) + "'"), 0).FirstOrDefault();
                                if (dt != null)
                                {
                                    auditInfo.OldValue = Convert.ToString(dt.Value);
                                }
                            }
                            else
                            {
                                auditInfo.OldValue = null;
                            }
                        }
                        else
                        {
                            auditInfo.OldValue = dbValues[property] != null && Convert.ToString(dbValues[property]) != string.Empty ? Convert.ToString(dbValues[property]) : null;
                            auditInfo.NewValue = entry.CurrentValues[property] != null && Convert.ToString(entry.CurrentValues[property]) != string.Empty ? Convert.ToString(entry.CurrentValues[property]) : null;
                        }
                        auditInfo.EncryptionCode =
                            CommonMethods.GetHashValue(
                                screenName.Trim() +
                                action.Trim() +
                                (auditInfo.OldValue != null ? auditInfo.OldValue : string.Empty) +
                                (auditInfo.NewValue != null ? auditInfo.NewValue : string.Empty) +
                                (auditInfo.AuditLogColumnId != null ? Convert.ToString(auditInfo.AuditLogColumnId) : string.Empty) +
                                (auditInfo.CreatedById != null ? Convert.ToString(auditInfo.CreatedById) : string.Empty) +
                                (Convert.ToString(auditInfo.CreatedDate)) +
                                (patientId != null ? Convert.ToString(patientId) : string.Empty) +
                                token.IPAddress.Trim() +
                                Convert.ToString(token.OrganizationID) +
                                Convert.ToString(token.LocationID));
                        auditInfoList.Add(auditInfo);
                    }
                }
            }
            return(auditInfoList);
        }
Example #23
0
        public static EntityEntry Refresh(this EntityEntry tracking, RefreshConflict refreshMode)
        {
            switch (refreshMode)
            {
            case RefreshConflict.StoreWins:
            {
                // When entity is already deleted in database, Reload sets tracking state to Detached.
                // When entity is already updated in database, Reload sets tracking state to Unchanged.
                tracking.Reload();         // Execute SELECT.
                                           // Hereafter, SaveChanges ignores this entity.
                break;
            }

            case RefreshConflict.ClientWins:
            {
                PropertyValues databaseValues = tracking.GetDatabaseValues();         // Execute SELECT.
                if (databaseValues == null)
                {
                    // When entity is already deleted in database, there is nothing for client to win against.
                    // Manually set tracking state to Detached.
                    tracking.State = EntityState.Detached;
                    // Hereafter, SaveChanges ignores this entity.
                }
                else
                {
                    // When entity is already updated in database, refresh original values, which go to in WHERE clause.
                    tracking.OriginalValues.SetValues(databaseValues);
                    // Hereafter, SaveChanges executes UPDATE/DELETE for this entity, with refreshed values in WHERE clause.
                }
                break;
            }

            case RefreshConflict.MergeClientAndStore:
            {
                PropertyValues databaseValues = tracking.GetDatabaseValues();         // Execute SELECT.
                if (databaseValues == null)
                {
                    // When entity is already deleted in database, there is nothing for client to merge with.
                    // Manually set tracking state to Detached.
                    tracking.State = EntityState.Detached;
                    // Hereafter, SaveChanges ignores this entity.
                }
                else
                {
                    // When entity is already updated, refresh original values, which go to WHERE clause.
                    PropertyValues originalValues = tracking.OriginalValues.Clone();
                    tracking.OriginalValues.SetValues(databaseValues);
                    // If database has an different value for a property, then retain the database value.
#if EF
                    var props = databaseValues.PropertyNames         // Navigation properties are not included.
                                .Where(property => !object.Equals(originalValues[property], databaseValues[property]));
#else
                    var props = databaseValues.Properties         // Navigation properties are not included.
                                .Where(property => !object.Equals(originalValues[property.Name], databaseValues[property.Name]));

                    foreach (var property in props)
                    {
                        if (!object.Equals(originalValues[property.Name], databaseValues[property.Name]))
                        {
                            tracking.Property(property.Name).IsModified = false;
                        }
                    }
#endif
                    // Hereafter, SaveChanges executes UPDATE/DELETE for this entity, with refreshed values in WHERE clause.
                }
                break;
            }
            }
            return(tracking);
        }
Example #24
0
        protected async Task <IActionResult> HandleDbUpdateConcurrencyException(DbUpdateConcurrencyException ex)
        {
            EntityEntry    exceptionEntry = ex.Entries.Single();
            object         clientValues   = exceptionEntry.Entity;
            PropertyValues databaseEntry  = exceptionEntry.GetDatabaseValues();

            if (databaseEntry == null)
            {
                ModelState.AddModelError(string.Empty, $"Unable to update the table with the requested changes. The {typeof(TEntity).Name} was deleted by another user.");
            }
            else
            {
                object         databaseValues     = databaseEntry.ToObject();
                string         entityName         = databaseValues.GetType().Name;
                PropertyInfo[] databaseProperties = databaseValues.GetType().GetProperties(),
                clientProperties = clientValues.GetType().GetProperties();
                foreach (PropertyInfo databaseProperty in databaseProperties)
                {
                    // Don't report changes to the following fields
                    if (databaseProperty.Name == "RowVersion" ||
                        databaseProperty.Name == "UpdatedBy" ||
                        databaseProperty.Name == "UpdatedDate")
                    {
                        continue;
                    }

                    PropertyInfo clientProperty = clientProperties.Where(d =>
                                                                         d.Name == databaseProperty.Name &&
                                                                         d.PropertyType == databaseProperty.PropertyType)
                                                  .FirstOrDefault();
                    if (clientProperty != null)
                    {
                        object databaseValue = databaseProperty.GetValue(databaseValues),
                               clientValue   = clientProperty.GetValue(clientValues);
                        if (databaseValue != null &&
                            clientValue != null &&
                            !databaseValue.Equals(clientValue))
                        {
                            ModelState.AddModelError($"{entityName}.{databaseProperty.Name}", $"New table value: {databaseValue} / Your conflicting value: {clientValue}");
                        }
                    }
                }
                string userName, updatedBy, updatedDate;
                try
                {
                    updatedBy   = databaseProperties.First(p => p.Name == "UpdatedBy").GetValue(databaseValues).ToString();
                    updatedDate = databaseProperties.First(p => p.Name == "UpdatedDate").GetValue(databaseValues).ToString();
                    if (updatedBy == Ids.SystemUserId)
                    {
                        userName = "******";
                    }
                    else
                    {
                        User user = await _accountManager.GetUserByIdAsync(updatedBy);

                        userName = user.FullName;
                    }
                }
                catch
                {
                    userName    = "******";
                    updatedDate = "01/01/1900 00:00:00";
                }

                ModelState.AddModelError(string.Empty, "The record you attempted to update was modified " +
                                         $"by {userName} at {updatedDate} after you queried the " +
                                         "original values. The update operation was canceled and both the new values in the database " +
                                         "and the conflicting values you supplied have been provided.");
            }
            string message = $"A DbUpdateConcurrencyException occurred when attempting to update {typeof(TEntity).Name}\r\nThe following message was returned:\r\n" + string.Join(" | ", ModelState.Values
                                                                                                                                                                                  .SelectMany(v => v.Errors)
                                                                                                                                                                                  .Select(e => e.ErrorMessage));

            _logger.LogDebug(message);

            return(BadRequest(ModelState));
        }
Example #25
0
        private bool EntryExistsInDb(DbContext context, EntityEntry entry)
        {
            bool exists = entry.GetDatabaseValues() != null;

            return(exists);
        }
        internal static TAutoHistory AutoHistory <TAutoHistory>(this EntityEntry entry, Func <TAutoHistory> createHistoryFactory)
            where TAutoHistory : AutoHistory
        {
            var history = createHistoryFactory();

            history.TableName = entry.Metadata.GetTableName();

            // Get the mapped properties for the entity type.
            // (include shadow properties, not include navigations & references)
            var properties = entry.Properties;

            dynamic json = new System.Dynamic.ExpandoObject();

            switch (entry.State)
            {
            case EntityState.Added:
                foreach (var prop in properties)
                {
                    if (prop.Metadata.IsKey() || prop.Metadata.IsForeignKey())
                    {
                        continue;
                    }
                    ((IDictionary <String, Object>)json)[prop.Metadata.Name] = prop.CurrentValue != null
                            ? prop.CurrentValue
                            : null;
                }

                // REVIEW: what's the best way to set the RowId?
                history.RowId   = "0";
                history.Kind    = EntityState.Added;
                history.Changed = JsonSerializer.Serialize(json);
                break;

            case EntityState.Modified:
                dynamic bef = new System.Dynamic.ExpandoObject();
                dynamic aft = new System.Dynamic.ExpandoObject();

                PropertyValues databaseValues = null;
                foreach (var prop in properties)
                {
                    if (prop.IsModified)
                    {
                        if (prop.OriginalValue != null)
                        {
                            if (!prop.OriginalValue.Equals(prop.CurrentValue))
                            {
                                ((IDictionary <String, Object>)bef)[prop.Metadata.Name] = prop.OriginalValue;
                            }
                            else
                            {
                                databaseValues = databaseValues ?? entry.GetDatabaseValues();
                                var originalValue = databaseValues.GetValue <object>(prop.Metadata.Name);
                                ((IDictionary <String, Object>)bef)[prop.Metadata.Name] = originalValue != null
                                        ? originalValue
                                        : null;
                            }
                        }
                        else
                        {
                            ((IDictionary <String, Object>)bef)[prop.Metadata.Name] = null;
                        }

                        ((IDictionary <String, Object>)aft)[prop.Metadata.Name] = prop.CurrentValue != null
                            ? prop.CurrentValue
                            : null;
                    }
                }

                ((IDictionary <String, Object>)json)["before"] = bef;
                ((IDictionary <String, Object>)json)["after"]  = aft;

                history.RowId   = entry.PrimaryKey();
                history.Kind    = EntityState.Modified;
                history.Changed = JsonSerializer.Serialize(json);
                break;

            case EntityState.Deleted:
                foreach (var prop in properties)
                {
                    ((IDictionary <String, Object>)json)[prop.Metadata.Name] = prop.OriginalValue != null
                            ? prop.OriginalValue
                            : null;
                }
                history.RowId   = entry.PrimaryKey();
                history.Kind    = EntityState.Deleted;
                history.Changed = JsonSerializer.Serialize(json);
                break;

            case EntityState.Detached:
            case EntityState.Unchanged:
            default:
                throw new NotSupportedException("AutoHistory only support Deleted and Modified entity.");
            }

            return(history);
        }