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