private void Ripple(TEntity instance, DataProviderDeleteSettings settings, Parameters parameters) { // Ripple each instance precisely once per DeleteStack traversal // (Note that this includes subtypes instances - i.e. the entire hierarchy is rippled from root call to RippleDelete) if (!DeleteStack.HasBeenRippledDuringCurrentTraversal(instance)) { if (!DeleteStack.IsResolved(instance)) { // Remember we've seen this instance DeleteStack.AddSeenObject(instance); // Count blockers before and after rippling in order to determine if instance can be added to the resolved list int numBlockers = DeleteStack.BlockersDuringCurrentTraversal.Count(); // Call virtual Ripple RippleDelete(instance, parameters, settings); // no errors => Can delete this object => Add to the resolved list if (numBlockers == DeleteStack.BlockersDuringCurrentTraversal.Count() && !DeleteStack.HasUnresolvedDependencies(instance)) { DeleteStack.MarkResolved(instance); // Do any deferred deletes DoDeferredDeletes(parameters, settings); } } } }
private void CheckResolved(IDataObject instanceBeingDeleted, IDataObject dependency) { if (!DeleteStack.IsResolved(dependency)) { AddBlockage("Unresolved dependency", instanceBeingDeleted, dependency); DeleteStack.AddUnresolvedDependency(instanceBeingDeleted, dependency); } }
protected void Delete <T>(T item, Parameters parameters, DataProviderDeleteSettings settings, TEntity currentInstance) where T : IDataObject { if (!DeleteStack.IsResolved(item)) { var db = ApplicationSettings.Container.Resolve <IDataProvider <T> >(); db.Delete(item, settings.SecurityFilterExpression, settings.Context, parameters, settings.SkipSecurity); CheckResolved(currentInstance, item); NeedResync = true; } }
protected void ReverseCascade(IDataObject item) { if (item != null) { // If item hasn't yet been seen during the current delete traversal, then defer-delete it in order that we (many side instances) are marked resolved *before* (one-side) item. if (!DeleteStack.HasBeenRippledDuringCurrentTraversal(item)) { AddDeferredDeleteItem(item); } } }
protected bool AddAnyBlockages <T>(string reason, TEntity instance, IEnumerable <T> dependencies) where T : IDataObject { bool blocked = false; foreach (var item in dependencies) { if (!DeleteStack.IsResolved(item)) { blocked = true; AddBlockage(reason, instance, item); } } return(blocked); }
protected void Save(TEntity instance) { if (DeleteStack.IsResolved(instance)) { return; } var db = ApplicationSettings.Container.Resolve <IDataProvider <TEntity> >() as IDataProvider2 <TEntity>; if (db != null) { db.Save(instance, new DataProviderSaveSettings { DeepDataMapping = false, Transaction = this.Transaction, SkipSecurity = true }); NeedResync = true; } }
protected void Save(IDataObject obj) { if (DeleteStack.IsResolved(obj)) { return; } dynamic db = ApplicationSettings.Container.Resolve <IEntityDataProvider>().GetDataProviderForEntity(obj) as IDataProvider2; if (db != null) { // Save a flat clone to ensure no relations explored during the save db.Save(obj.Clone(recursive: false), new DataProviderSaveSettings { DeepDataMapping = false, Transaction = this.Transaction, SkipSecurity = true }); NeedResync = true; } }
protected void AddBlockage(string reason, IDataObject blocked, IDataObject blocker) { if (DeleteStack.IsResolved(blocker)) { return; } var blockage = new DeleteBlockage { Reason = reason, Blocked = blocked, Blocker = blocker, DeleteRoot = DeleteStack.RootObject, Parameters = this.Parameters }; DeleteStack.BlockersDuringCurrentTraversal.Add(blockage); DeleteStack.AddUnresolvedDependency(blocked, blocker); // Trace var explain = ApplicationSettings.Container.Resolve <IDeleteBlockageExplanationProvider>(); DeleteStack.Trace("BLOCKER: " + explain.Explain(blockage)); }