/// <summary> /// Truncates all previous events for instances when a state change occurs /// </summary> public void Truncate() { HashSet <ModelInstance> removeEventInstances = new HashSet <ModelInstance>(); for (var transaction = this; transaction != null; transaction = transaction.PreviousTransaction) { // Process the transaction log in reverse order, searching for changes to remove var node = events.Last; while (node != null) { var evt = node.Value; var previous = node.Previous; if (evt is ModelSaveEvent) { ModelSaveEvent saveEvent = (ModelSaveEvent)evt; removeEventInstances.UnionWith(saveEvent.Added); removeEventInstances.UnionWith(saveEvent.Deleted); removeEventInstances.UnionWith(saveEvent.Modified); transaction.events.Remove(node); } else if (removeEventInstances.Contains(evt.Instance)) { transaction.events.Remove(node); } node = previous; } } }
/// <summary> /// Records <see cref="ModelEvent"/> occurences within the current context. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void context_Event(object sender, ModelEvent e) { // Only track events that change the model. // Don't track changes to cached objects. if (e is ITransactedModelEvent && !e.Instance.IsCached) { // Track id mappings for new instances created during the transaction if (e is ModelInitEvent.InitNew) { RegisterNewInstance(e.Instance); } // Populate save events with ids that have changed during the transaction else if (e is ModelSaveEvent) { HashSet <ModelInstance> added = new HashSet <ModelInstance>(); HashSet <ModelInstance> modified = new HashSet <ModelInstance>(); HashSet <ModelInstance> deleted = new HashSet <ModelInstance>(); for (var transaction = this; transaction != null; transaction = transaction.PreviousTransaction) { // Process the transaction log in reverse order, searching for instances // that were persisted by the save event for (var node = transaction.events.Last; node != null; node = node.Previous) { var evt = node.Value; // Stop processing if a previous save event is encountered if (evt is ModelSaveEvent) { goto UpdateSave; } // Deleted if (evt.Instance.IsDeleted) { deleted.Add(evt.Instance); } // Added else if (evt is ModelInitEvent.InitNew && !evt.Instance.IsNew) { added.Add(evt.Instance); } // Modified else if (!evt.Instance.IsNew && !evt.Instance.IsModified) { modified.Add(evt.Instance); } } } UpdateSave : ModelSaveEvent saveEvent = (ModelSaveEvent)e; saveEvent.Added = added.ToArray(); saveEvent.Deleted = deleted.ToArray(); saveEvent.Modified = modified.Except(saveEvent.Added).Except(saveEvent.Deleted).ToArray(); } // Add the transacted event to the list of events for the transaction events.AddLast(e); } }