Beispiel #1
0
 public ConflictException(object error = null, DbUpdateConcurrencyException exception = null)
     : base(StatusCodes.Status409Conflict, error, exception)
 {
 }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        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();
        }
Beispiel #5
0
 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);
Beispiel #8
0
 //
 // 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);
 }
Beispiel #9
0
 //
 // 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);
 }
Beispiel #10
0
 public DbUpdateConcurrencyExceptionBase()
 {
     _dbUpdateConcurrencyException = new DbUpdateConcurrencyException();
 }
Beispiel #11
0
 public DbUpdateConcurrencyExceptionBase(Exception exception)
 {
     _dbUpdateConcurrencyException = exception as DbUpdateConcurrencyException;
 }
Beispiel #12
0
        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++;
            }
        }
Beispiel #13
0
 internal abstract string StringHandler1(object[] paras, DbUpdateConcurrencyException db);
Beispiel #14
0
        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状态
                }
            }
        }
Beispiel #15
0
 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();
        }
Beispiel #17
0
        public void DbUpdateConcurrencyException_exposes_public_string_constructor()
        {
            var ex = new DbUpdateConcurrencyException("Foo");

            Assert.Equal("Foo", ex.Message);
        }
Beispiel #18
0
 public static string Error(this DbUpdateConcurrencyException ex, MethodBase mb = null)
 {
     return(Error((DbUpdateException)ex, mb));
 }
 public ConcurrencyException(DbUpdateConcurrencyException exception)
 {
     frameworkException = exception;
 }
Beispiel #20
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));
        }
 public static void ConcurrencyExceptionNotHandled(
     ILogger logger,
     DbUpdateConcurrencyException exception)
 => _concurrencyExceptionNotHandled.Invoke(
     logger,
     exception);
Beispiel #22
0
 public VehicleNotExistException(DbUpdateConcurrencyException updateConcurrencyException) : base("Vehicle not exist.", updateConcurrencyException)
 {
 }