public static int SubmitSaveChanges(this DbContext dbContext, bool acceptAllChangesOnSuccess = true) { dbContext.NotNull(nameof(dbContext)); CheckDisposed(dbContext); var dependencies = dbContext.GetService <IDbContextDependencies>(); dependencies.UpdateLogger.SaveChangesStarting(dbContext); TryDetectChanges(dbContext); try { var entitiesSaved = dependencies.StateManager.SaveChanges(acceptAllChangesOnSuccess); dependencies.UpdateLogger.SaveChangesCompleted(dbContext, entitiesSaved); return(entitiesSaved); } catch (DbUpdateConcurrencyException exception) { dependencies.UpdateLogger.OptimisticConcurrencyException(dbContext, exception); throw; } catch (Exception exception) { dependencies.UpdateLogger.SaveChangesFailed(dbContext, exception); throw; } }
public static void ConcurrentUpdates <TEntity>(this DbContext dbContext, DbUpdateConcurrencyException exception, Func <TEntity, bool> predicate, string updatePropertyName = null) where TEntity : class { dbContext.NotNull(nameof(dbContext)); exception.NotNull(nameof(exception)); foreach (var entry in exception.Entries) { if (entry.Entity is TEntity) { foreach (var property in entry.Metadata.GetProperties()) { var dbEntity = dbContext.Set <TEntity>().AsNoTracking().Single(predicate); var dbEntityEntry = dbContext.Entry(dbEntity); //var proposedValue = entry.Property(property.Name).CurrentValue; //var originalValue = entry.Property(property.Name).OriginalValue; //var databaseValue = dbEntityEntry.Property(property.Name).CurrentValue; // 如果要更新的属性名不为空且等于当前属性,或要更新的属性名为空,则并发更新此属性 if ((updatePropertyName.IsNotEmpty() && property.Name == updatePropertyName) || updatePropertyName.IsEmpty()) { // Update original values to entry.Property(property.Name).OriginalValue = dbEntityEntry.Property(property.Name).CurrentValue; if (updatePropertyName.IsNotEmpty()) { break; // 如果只更新当前属性,则跳出属性遍历 } } } } else { throw new NotSupportedException("Don't know how to handle concurrency conflicts for " + entry.Metadata.Name); } } dbContext.SaveChanges(); }
public static async Task <int> SubmitSaveChangesAsync(this DbContext dbContext, bool acceptAllChangesOnSuccess = true, CancellationToken cancellationToken = default) { dbContext.NotNull(nameof(dbContext)); CheckDisposed(dbContext); var dependencies = dbContext.GetService <IDbContextDependencies>(); dependencies.UpdateLogger.SaveChangesStarting(dbContext); TryDetectChanges(dbContext); try { var entitiesSaved = await dependencies.StateManager .SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken) .ConfigureAwait(); dependencies.UpdateLogger.SaveChangesCompleted(dbContext, entitiesSaved); return(entitiesSaved); } catch (DbUpdateConcurrencyException exception) { dependencies.UpdateLogger.OptimisticConcurrencyException(dbContext, exception); throw; } catch (Exception exception) { dependencies.UpdateLogger.SaveChangesFailed(dbContext, exception); throw; } }