public static DbEntityEntry Refresh(this DbEntityEntry tracking, RefreshConflict refreshMode) { tracking.NotNull(nameof(tracking)); 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: { DbPropertyValues 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.MergeClinetAndStore: { DbPropertyValues 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. DbPropertyValues originalValues = tracking.OriginalValues.Clone(); tracking.OriginalValues.SetValues(databaseValues); // If database has an different value for a property, then retain the database value. databaseValues.PropertyNames // Navigation properties are not included. .Where(property => !object.Equals(originalValues[property], databaseValues[property])) .ForEach(property => tracking.Property(property).IsModified = false); // Hereafter, SaveChanges executes UPDATE/DELETE for this entity, with refreshed values in WHERE clause. } break; } } return(tracking); }
public async Task <ServiceResult <CourseResponse> > UpdateCourse(CourseRequest request) { var courseEntity = Mapper.Map <CourseRequest, Course>(request); var modelState = new Dictionary <string, string[]>(); _unitOfWork.CourseRepository.Update(courseEntity); // Handle Conflicts here int result; if (request.ConflictStrategy == ResolveStrategy.ShowUnresolvedConflicts) { var resolveConflicts = ConcurrencyHelper.ResolveConflicts(courseEntity, modelState); result = await _unitOfWork.SaveAsync(resolveConflicts, userResolveConflict : true); } else { RefreshConflict refreshMode = (RefreshConflict)request.ConflictStrategy; if (!EnumExtensions.IsFlagDefined(refreshMode)) { refreshMode = RefreshConflict.StoreWins; } result = _unitOfWork.SaveSingleEntry(refreshMode); } return(await GetServiceResult(courseEntity, modelState, result)); }
public int SaveMultipleEntries(RefreshConflict refreshMode, int retryCount = 3) { Action <IEnumerable <EntityEntry> > resolveConflicts = (entries) => { (entries as List <EntityEntry>).ForEach(entry => entry.Refresh(refreshMode)); }; return(_context.SaveChangesAsync(resolveConflicts, retryCount).GetAwaiter().GetResult()); }
public int SaveSingleEntry(RefreshConflict refreshMode, int retryCount = 3) { Action <IEnumerable <EntityEntry> > resolveConflicts = (entries) => { entries.Single().Refresh(refreshMode); }; return(_context.SaveChangesAsync(resolveConflicts, retryCount).GetAwaiter().GetResult()); }
public static int SaveChanges(this DbContext context, RefreshConflict refreshMode, int retryCount = 3) { if (retryCount <= 0) { throw new ArgumentOutOfRangeException(nameof(retryCount), $"{retryCount}必须大于0"); } return(context.SaveChanges( conflicts => conflicts.ToList().ForEach(tracking => tracking.Refresh(refreshMode)), retryCount)); }
public static DbEntityEntry Refresh(this DbEntityEntry tracking, RefreshConflict refreshMoode) { switch (refreshMoode) { case RefreshConflict.StoreWins: { //当实体被删除时,重新加载,设置追踪状态为Detached //当实体被更新时,重新加载,设置追踪状态为Unchanged tracking.Reload(); break; } case RefreshConflict.ClientWins: { DbPropertyValues databaseValues = tracking.GetDatabaseValues(); if (databaseValues == null) { //当实体被删除时,设置追踪状态为Detached, 此时客户端无所谓获胜 tracking.State = EntityState.Detached; } else { //当实体被更新时,刷新数据库原始值 tracking.OriginalValues.SetValues(databaseValues); } break; } case RefreshConflict.MergeClientAndStore: { DbPropertyValues databaseValues = tracking.GetDatabaseValues(); if (databaseValues == null) { //当实体被删除时,设置追踪状态为Detached, 当然此时客户端没有合并的数据,并设置追踪状态为Detached tracking.State = EntityState.Detached; } else { //当实体被更新时 DbPropertyValues originValues = tracking.OriginalValues.Clone(); tracking.OriginalValues.SetValues(databaseValues); //如果数据库中对于属性有不同值,保留数据库中的值 databaseValues.PropertyNames.Where(property => !object.Equals(originValues[property], databaseValues[property])) .ToList() .ForEach(property => tracking.Property(property).IsModified = false); } break; } } return(tracking); }
public static DbEntityEntry Refresh(this DbEntityEntry tracking, RefreshConflict refreshMode) { switch (refreshMode) { case RefreshConflict.StoreWins: //当实体被删除时,重新加载,设置状态为Detached tracking.Reload(); break; case RefreshConflict.ClientWins: { DbPropertyValues databaseValues = tracking.GetDatabaseValues(); if (databaseValues == null) { tracking.State = EntityState.Deleted; } else { tracking.OriginalValues.SetValues(databaseValues); } break; } case RefreshConflict.MergeClientAndStore: { DbPropertyValues databaseValues = tracking.GetDatabaseValues(); if (databaseValues == null) { tracking.State = EntityState.Deleted; } else { DbPropertyValues originalValues = tracking.OriginalValues.Clone(); tracking.OriginalValues.SetValues(databaseValues); databaseValues.PropertyNames.Where(property => !object.Equals(originalValues[property], databaseValues[property])).ToList().ForEach(property => tracking.Property(property).IsModified = false); } break; } } return(tracking); }
public static int SaveChanges( this DbContext context, RefreshConflict refreshMode, RetryStrategy retryStrategy) => context.SaveChanges( conflicts => conflicts.ToList().ForEach(tracking => tracking.Refresh(refreshMode)), retryStrategy);
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); }
public static async Task <EntityEntry> RefreshAsync(this EntityEntry tracking, RefreshConflict refreshMode) { switch (refreshMode) { case RefreshConflict.StoreWins: { await tracking.ReloadAsync(); break; } case RefreshConflict.ClientWins: { PropertyValues databaseValues = await tracking.GetDatabaseValuesAsync(); if (databaseValues == null) { tracking.State = EntityState.Detached; } else { tracking.OriginalValues.SetValues(databaseValues); } break; } case RefreshConflict.MergeClientAndStore: { PropertyValues databaseValues = await tracking.GetDatabaseValuesAsync(); if (databaseValues == null) { tracking.State = EntityState.Detached; } else { PropertyValues originalValues = tracking.OriginalValues.Clone(); #if !EF originalValues.SetValues(tracking.OriginalValues); #endif tracking.OriginalValues.SetValues(databaseValues); #if EF databaseValues.PropertyNames .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])) .ForEach(property => tracking.Property(property.Name).IsModified = false); #endif } break; } } return(tracking); }