private ObjectVisitationHelper(ObjectVisitationHelper other) { _objectSet = other._objectSet.ToDictionary( x => x.Key, y => y.Value, other._objectSet.Comparer); }
/// <summary> /// Helper method which initializes the given reference to ObjectVisitationHelper /// if it is null. /// </summary> /// <param name="visitationHelper">Reference to ObjectVisitationHelper</param> public static void EnsureCreated(ref ObjectVisitationHelper visitationHelper) { if (visitationHelper == null) { visitationHelper = new ObjectVisitationHelper(); } }
// Recursively get modified properties public static IEnumerable<IEnumerable<string>> GetModifiedProperties (this ITrackable item, ObjectVisitationHelper visitationHelper = null) { // Prevent endless recursion ObjectVisitationHelper.EnsureCreated(ref visitationHelper); if (!visitationHelper.TryVisit(item)) yield break; foreach (var navProp in item.GetNavigationProperties()) { foreach (var refProp in navProp.AsReferenceProperty()) { foreach (var modifiedProps in refProp.EntityReference.GetModifiedProperties(visitationHelper)) { yield return modifiedProps; } } foreach (var colProp in navProp.AsCollectionProperty()) { foreach (ITrackable child in colProp.EntityCollection) { foreach (var modifiedProps in child.GetModifiedProperties(visitationHelper)) { yield return modifiedProps; } } } } yield return item.ModifiedProperties; }
// Recursively get tracking states public static IEnumerable<TrackingState> GetTrackingStates (this ITrackable item, TrackingState? trackingState = null, ObjectVisitationHelper visitationHelper = null) { // Prevent endless recursion ObjectVisitationHelper.EnsureCreated(ref visitationHelper); if (!visitationHelper.TryVisit(item)) yield break; foreach (var navProp in item.GetNavigationProperties()) { foreach (var refProp in navProp.AsReferenceProperty()) { foreach (var state in refProp.EntityReference.GetTrackingStates(visitationHelper: visitationHelper)) { if (trackingState == null || state == trackingState) yield return state; } } foreach (var colProp in navProp.AsCollectionProperty()) { foreach (ITrackable child in colProp.EntityCollection) { foreach (var state in child.GetTrackingStates(visitationHelper: visitationHelper)) { if (trackingState == null || state == trackingState) yield return state; } } } } yield return item.TrackingState; }
// Recursively set tracking state public static void SetTrackingState(this ITrackable item, TrackingState state, ObjectVisitationHelper visitationHelper = null) { // Prevent endless recursion ObjectVisitationHelper.EnsureCreated(ref visitationHelper); if (!visitationHelper.TryVisit(item)) return; foreach (var navProp in item.GetNavigationProperties()) { foreach (var refProp in navProp.AsReferenceProperty()) { refProp.EntityReference.SetTrackingState(state, visitationHelper); refProp.EntityReference.TrackingState = state; } foreach (var colProp in navProp.AsCollectionProperty()) { foreach (ITrackable child in colProp.EntityCollection) { child.SetTrackingState(state, visitationHelper); child.TrackingState = state; } } } }
private static void AcceptChanges(this ITrackable item, ObjectVisitationHelper visitationHelper) { ObjectVisitationHelper.EnsureCreated(ref visitationHelper); // Prevent endless recursion if (visitationHelper != null && !visitationHelper.TryVisit(item)) { return; } // Set tracking state for child collections foreach (var navProp in item.GetNavigationProperties()) { // Apply changes to 1-1 and M-1 properties foreach (var refProp in navProp.AsReferenceProperty()) { refProp.EntityReference.AcceptChanges(visitationHelper); } // Apply changes to 1-M properties foreach (var colProp in navProp.AsCollectionProperty <IList>()) { var items = colProp.EntityCollection; var count = items.Count; for (int i = count - 1; i > -1; i--) { // Stop recursion if trackable hasn't been visited var trackable = items[i] as ITrackable; if (trackable != null) { if (trackable.TrackingState == TrackingState.Deleted) { // Remove items marked as deleted items.RemoveAt(i); } else { // Recursively accept changes on trackable trackable.AcceptChanges(visitationHelper); } } } } } // Set tracking state and clear modified properties item.TrackingState = TrackingState.Unchanged; item.ModifiedProperties = null; }
// Recursively get entity states public static IEnumerable<EntityState> GetEntityStates(this DbContext context, ITrackable item, EntityState? entityState = null, ObjectVisitationHelper visitationHelper = null) { // Prevent endless recursion ObjectVisitationHelper.EnsureCreated(ref visitationHelper); if (!visitationHelper.TryVisit(item)) yield break; foreach (var colProp in item.GetNavigationProperties().OfCollectionType()) { foreach (ITrackable child in colProp.EntityCollection) { foreach (var state in context.GetEntityStates(child, visitationHelper: visitationHelper)) { if (entityState == null || state == entityState) yield return state; } } } yield return context.Entry(item).State; }
/// <summary> /// Helper method which initializes the given reference to ObjectVisitationHelper /// if it is null. /// </summary> /// <param name="visitationHelper">Reference to ObjectVisitationHelper</param> public static void EnsureCreated(ref ObjectVisitationHelper visitationHelper) { if (visitationHelper == null) visitationHelper = new ObjectVisitationHelper(); }