private static object CreateWithValues(PropertyValues values, Type type = null) { if (type == null) { type = typeof(T); } try { return(values.ToObject()); } catch { var entity = Activator.CreateInstance(type); Debug.WriteLine(values.ToObject()); foreach (var p in values.Properties) { var name = p.Name; var value = values.GetValue <object>(name); var property = type.GetProperty(name); if (value == null) { continue; } var propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; property.SetValue(entity, Convert.ChangeType(value, propertyType), null); } return(entity); } }
private static void AddHistoricalEntity(DbContext dbContext, PropertyValues originalValues, DateTimeOffset moment) { var original = Mapper.Map <THistoricalEntity>(originalValues.ToObject()); original.ValidTo = moment; dbContext.Set <THistoricalEntity>().Add(original); }
/// <summary> /// This method creates a changeset style model for Changes being made to the entity. /// This can be used to create audit logs or event queues in conjunction with IEntityOperationEventSink /// </summary> /// <param name="timestamp"></param> /// <param name="entity"></param> /// <param name="operation"></param> /// <param name="currentValues"></param> /// <param name="originalValues"></param> /// <returns></returns> protected string TrackChange(T entity, EntityOperationType operation = EntityOperationType.Unknown, PropertyValues currentValues = null, PropertyValues originalValues = null, byte[] timestamp = null) { bool nonAuditable = typeof(INonAuditable).IsAssignableFrom(typeof(T)); if (nonAuditable.Equals(false)) { //create new AuditLog object AuditLog change = new AuditLog(); try { //define properties in object change.Id = Guid.NewGuid(); change.ObjectId = entity.Id; change.CreatedBy = _caller.Identity == null ? entity.CreatedBy : _caller.Identity.Name; change.CreatedOn = DateTime.UtcNow; if (timestamp == null) { timestamp = new byte[1]; } change.Timestamp = timestamp; //name of service that is being changed change.ServiceName = entity.ToString(); //name of how entity is being changed (Add, Update, Delete) change.MethodName = operation.ToString(); change.ParametersJson = ""; //TODO: update to show parameters of method change.ExceptionJson = ""; //TODO: update to show any exceptions that arise change.ChangedFromJson = (originalValues == null) ? null : JsonConvert.SerializeObject(originalValues.ToObject()); change.ChangedToJson = (currentValues == null) ? null : JsonConvert.SerializeObject(currentValues.ToObject()); //add object to AuditLog data table DbContext.Add(change); DbContext.SaveChanges(); } catch (Exception ex) { throw new EntityOperationException(ex); } //return audit log object as a string return(change.ToString()); } return(new InvalidOperationException().Message); }
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)); }