//see https://blogs.msdn.microsoft.com/dotnet/2016/09/29/implementing-seeding-custom-conventions-and-interceptors-in-ef-core-1-0/ //for why I call DetectChanges before ChangeTracker, and why I then turn ChangeTracker.AutoDetectChangesEnabled off/on around SaveChanges /// <summary> /// This will validate any entity classes that will be added or updated /// If the validation does not produce any errors then SaveChanges will be called /// </summary> /// <param name="context"></param> /// <param name="config"></param> /// <returns>List of errors, empty if there were no errors</returns> public static IStatusGeneric SaveChangesWithValidation(this DbContext context, IGenericBizRunnerConfig config = null) { var status = context.ExecuteValidation(); if (status.HasErrors) { return(status); } context.ChangeTracker.AutoDetectChangesEnabled = false; try { context.SaveChanges(); } catch (Exception e) { var exStatus = config?.SaveChangesExceptionHandler(e, context); if (exStatus == null) { throw; //error wasn't handled, so rethrow } status.CombineErrors(exStatus); } finally { context.ChangeTracker.AutoDetectChangesEnabled = true; } return(status); }
//------------------------------------------------------------------- //private methods private static IStatusGeneric SaveChangesWithExtras(this DbContext context, IGenericBizRunnerConfig config, bool turnOffChangeTracker = false) { var status = config?.BeforeSaveChanges != null ? config.BeforeSaveChanges(context) : new StatusGenericHandler(); if (status.HasErrors) { return(status); } if (turnOffChangeTracker) { context.ChangeTracker.AutoDetectChangesEnabled = false; } try { context.SaveChanges(); } catch (Exception e) { var exStatus = config?.SaveChangesExceptionHandler(e, context); if (exStatus == null) { throw; //error wasn't handled, so rethrow } status.CombineErrors(exStatus); } finally { context.ChangeTracker.AutoDetectChangesEnabled = true; } return(status); }