public ConflictException(object error = null, DbUpdateConcurrencyException exception = null) : base(StatusCodes.Status409Conflict, error, exception) { }
/// <summary> /// Tries the resolve concurrency exception. /// </summary> /// <param name="duce">The duce.</param> /// <returns>true if succeeded; otherwise, false</returns> private bool TryResolveConcurrencyException(DbUpdateConcurrencyException duce) { bool concurrencyIssueResolved = false; // If a save attempt throws a concurrency exception, we'll apply some general rules to see if we can resolve it automatically. // We assume that, if someone else updated FieldA, and we're only updating FieldB, then we can merge those changes. // Iterate through all the entities that had a concurrency violation foreach (var se in duce.Entries) { // For each entity, we need to consider the values the entity has/had: // 1.) When this repository first loaded it (entityOriginal) // 2.) When we attempted to save it (entityCurrent) // and 3.) currently in the database (storeCurrent). var entityOriginal = se.OriginalValues.Clone(); var entityCurrent = se.CurrentValues.Clone(); se.Reload(); var storeCurrent = se.OriginalValues.Clone(); // Now walk through each field and determine if: this repo changed it, the store changed it, both, or neither. foreach (var propName in entityCurrent.PropertyNames) { bool clientChanged = ((entityOriginal[propName] != null) && entityOriginal[propName].GetType().IsValueType) ? !entityOriginal[propName].Equals(entityCurrent[propName]) : (entityOriginal[propName] != entityCurrent[propName]); bool storeChanged = ((entityOriginal[propName] != null) && entityOriginal[propName].GetType().IsValueType) ? !entityOriginal[propName].Equals(storeCurrent[propName]) : (entityOriginal[propName] != storeCurrent[propName]); if (clientChanged && storeChanged) { // If changed to same value, let it go. if (IsValueType(entityOriginal[propName] ?? storeCurrent[propName]) ? (entityOriginal[propName] != null ? entityCurrent[propName].Equals(storeCurrent[propName]) : storeCurrent[propName].Equals(entityCurrent[propName])) : (entityCurrent[propName] == storeCurrent[propName])) { // Both changed, but we changed it to the same value, so no harm. concurrencyIssueResolved = true; } else { // So, someone else changed the value for this field, and we're trying to change it, and we're NOT trying to change it to the same value. // We can't resolve this. throw new Exception( string.Format( "Unable to resolve concurrency violation. Attempted to change {0}.{1} from \"{2}\" to \"{3}\", but it was updated elsewhere to \"{4}\".", se.Entity.GetType(), propName, entityOriginal[propName], entityCurrent[propName], storeCurrent[propName]), duce); } } else if (clientChanged) { // Only this repo has tried to change the field. Restore our change. se.Property(propName).CurrentValue = entityCurrent[propName]; concurrencyIssueResolved = true; } else if (storeChanged) { concurrencyIssueResolved = true; } } } return(concurrencyIssueResolved); }
private static void EvaluateExeption(ILogger logger, IEnumerable <LogCategory> logCategories, string methodName, DbUpdateConcurrencyException dbc_ex) { if (dbc_ex.Entries != null) { foreach (DbEntityEntry result in dbc_ex.Entries.Where(f => f.Entity != null)) { logger.WriteWarning(new LogMessage(string.Concat("Type: ", result.Entity.GetType().Name, " was part of the problem")), logCategories); } } logger.WriteError(dbc_ex, logCategories); throw new DSWException(string.Concat(methodName, ".UpdateConcurrencyException -> ", dbc_ex.Message), dbc_ex, DSWExceptionCode.DB_ConcurrencyError); }
public void A_DbUpdateConcurrencyException_is_a_concurrency_exception() { var exception = new DbUpdateConcurrencyException(); exception.IsConcurrencyException().Should().BeTrue(); }
public CustomConcurrencyException(string message, DbUpdateConcurrencyException innerException) : base(message, innerException) { }
internal override string StringHandler1(object[] paras, DbUpdateConcurrencyException db) { return(string.Format("添加用户ID {0} 到角色 {1} 时出错:" + db.Message + "\t\t", paras[0], paras[1])); }
public static void ConcurrencyExceptionHandling( ILogger logger, DbUpdateConcurrencyException exception) => _concurrencyExceptionHandling.Invoke( logger, exception);
// // Summary: // Initializes a new instance of the System.Data.Entity.Infrastructure.DbUpdateException // class. // // Parameters: // message: // The message. public DbUpdateConcurrencyExceptionBase(string message) { _dbUpdateConcurrencyException = new DbUpdateConcurrencyException(message); }
// // Summary: // Initializes a new instance of the System.Data.Entity.Infrastructure.DbUpdateException // class. // // Parameters: // message: // The message. // // innerException: // The inner exception. public DbUpdateConcurrencyExceptionBase(string message, Exception innerException) { _dbUpdateConcurrencyException = new DbUpdateConcurrencyException(message, innerException); }
public DbUpdateConcurrencyExceptionBase() { _dbUpdateConcurrencyException = new DbUpdateConcurrencyException(); }
public DbUpdateConcurrencyExceptionBase(Exception exception) { _dbUpdateConcurrencyException = exception as DbUpdateConcurrencyException; }
public static void AppendDbUpdateConcurrencyException(StringBuilder stringBuilder, DbUpdateConcurrencyException ex) { stringBuilder.AppendMarkdownLine("DbUpdateConcurrencyException data: "); int i = 1; foreach (var e in ex.Entries) { stringBuilder.AppendMarkdownProperty(i.ToString(), e.Entity.GetType().FullName); var propertyNames = e.CurrentValues.PropertyNames; foreach (var p in propertyNames) { stringBuilder.AppendMarkdownProperty(" " + p, (e.CurrentValues.GetValue <object>(p)?.ToString()) ?? "(null)"); } i++; } }
internal abstract string StringHandler1(object[] paras, DbUpdateConcurrencyException db);
private void HandleDbUpdateConcurrencyExceptionReload(object[] paras, BuildDbUpdateConcurrencyExceptionFormatStringEventHandler stringHandler1, DbUpdateConcurrencyException db) { //先记录Debug日志 string temp = stringHandler1.Invoke(paras, db); LogHelper.Debug(temp); System.Diagnostics.Debug.WriteLine(temp); //发现并发异常,先通过异常对象抓到哪个对象的当前值与数据库不一致 if (db != null && db.Entries != null && db.Entries.Count() > 0) {//对所有不一致的对象,都把他们的“原始值”置为数据库的值 var entries = db.Entries.ToArray(); foreach (var entry in entries) { var dbvalues = entry.GetDatabaseValues(); var originValues = entry.OriginalValues; var currentValues = entry.CurrentValues; entry.OriginalValues.SetValues(entry.GetDatabaseValues()); entry.Reload();//最后重新加载对象,变成unchanged状态 } } }
public ConflictException(DbUpdateConcurrencyException exception) : this(exception.Message, exception) { }
public async Task PutUser_UserHasChangedInDatabase_ReturnsBadRequest() { // Arrange var mockConfiguration = new Mock <Microsoft.Extensions.Configuration.IConfiguration>(); var mockLogger = new Mock <ILogger <AccountController> >(); var mockUmService = new Mock <IUserManagementService>(); var mockHelperService = new Mock <IHelperService>(); var mockMapper = new Mock <IMapper>(); var controller = new UsersController(mockConfiguration.Object, mockLogger.Object, mockUmService.Object, mockMapper.Object, mockHelperService.Object); var aOld = new UpdateUserModel { Id = "a", FirstName = "a", LastName = "b", Email = "[email protected]", Role = "employee" }; var aNew = new UpdateUserModel { Id = "a", FirstName = "b", LastName = "c", Email = "[email protected]", Role = "supervisor" }; ApplicationUser oldUser = new ApplicationUser { Id = "a", FirstName = "a", LastName = "b", Email = "[email protected]" }; ApplicationUser newUser = new ApplicationUser { Id = "a", FirstName = "b", LastName = "c", Email = "[email protected]" }; mockUmService.Setup(umService => umService.FindUserAsync("a")) .ReturnsAsync(oldUser) .Verifiable(); mockUmService.Setup(umService => umService.IsEmailInUseAsync("[email protected]", "a")) .ReturnsAsync(false) .Verifiable(); mockMapper.Setup(mapper => mapper.Map(aNew, oldUser)) .Callback <UpdateUserModel, ApplicationUser>((userModel, user) => { user.FirstName = userModel.FirstName; user.LastName = userModel.LastName; user.Email = userModel.Email; }) .Returns(newUser) .Verifiable(); DbUpdateConcurrencyException dbUpdateConcurrencyException = new DbUpdateConcurrencyException("Exception", new List <IUpdateEntry>() { new Mock <IUpdateEntry>().Object }); mockUmService.Setup(umService => umService.UpdateUserAsync(oldUser, "supervisor", It.IsAny <byte[]>())) .ThrowsAsync(dbUpdateConcurrencyException) .Verifiable(); mockHelperService.Setup(helperService => helperService.RetrieveEntity(dbUpdateConcurrencyException)) .ReturnsAsync((PropertyValues)null); // Act var result = await controller.PutUser("a", aNew); // Assert var actionResult = Assert.IsType <BadRequestObjectResult>(result); mockUmService.Verify(); }
public void DbUpdateConcurrencyException_exposes_public_string_constructor() { var ex = new DbUpdateConcurrencyException("Foo"); Assert.Equal("Foo", ex.Message); }
public static string Error(this DbUpdateConcurrencyException ex, MethodBase mb = null) { return(Error((DbUpdateException)ex, mb)); }
public ConcurrencyException(DbUpdateConcurrencyException exception) { frameworkException = exception; }
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)); }
public static void ConcurrencyExceptionNotHandled( ILogger logger, DbUpdateConcurrencyException exception) => _concurrencyExceptionNotHandled.Invoke( logger, exception);
public VehicleNotExistException(DbUpdateConcurrencyException updateConcurrencyException) : base("Vehicle not exist.", updateConcurrencyException) { }