Skip to content

Commit

Permalink
New ChangeTracker events
Browse files Browse the repository at this point in the history
- Tracking
- StateChanging
- DetectingChanges
- DetectedChanges

Part of #626
Fixes #27093
Fixes #16256
  • Loading branch information
ajcvickers committed Jun 24, 2022
1 parent 62fb246 commit fa02b24
Show file tree
Hide file tree
Showing 15 changed files with 1,191 additions and 203 deletions.
46 changes: 46 additions & 0 deletions src/EFCore/ChangeTracking/ChangeTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,16 @@ public virtual void TrackGraph<TState>(

private IEntityEntryGraphIterator GraphIterator { get; }

/// <summary>
/// An event fired when an entity is about to be tracked by the context, either because it is returned
/// from a tracking query, or because it is being attached or added to the context.
/// </summary>
public event EventHandler<EntityTrackingEventArgs> Tracking
{
add => StateManager.Tracking += value;
remove => StateManager.Tracking -= value;
}

/// <summary>
/// An event fired when an entity is tracked by the context, either because it was returned
/// from a tracking query, or because it was attached or added to the context.
Expand All @@ -342,6 +352,20 @@ public event EventHandler<EntityTrackedEventArgs> Tracked
remove => StateManager.Tracked -= value;
}

/// <summary>
/// An event fired when an entity that is tracked by the associated <see cref="DbContext" /> is moving
/// from one <see cref="EntityState" /> to another.
/// </summary>
/// <remarks>
/// Note that this event does not fire for entities when they are first tracked by the context.
/// Use the <see cref="Tracking" /> event to get notified when the context begins tracking an entity.
/// </remarks>
public event EventHandler<EntityStateChangingEventArgs> StateChanging
{
add => StateManager.StateChanging += value;
remove => StateManager.StateChanging -= value;
}

/// <summary>
/// An event fired when an entity that is tracked by the associated <see cref="DbContext" /> has moved
/// from one <see cref="EntityState" /> to another.
Expand All @@ -356,6 +380,28 @@ public event EventHandler<EntityStateChangedEventArgs> StateChanged
remove => StateManager.StateChanged -= value;
}

/// <summary>
/// An event fired when detecting changes to the entity graph or a single entity is about to happen, either through an
/// explicit call to <see cref="DetectChanges" /> or <see cref="EntityEntry.DetectChanges" />, or automatically, such as part of
/// executing <see cref="DbContext.SaveChanges()" /> or <see cref="DbContext.SaveChangesAsync(System.Threading.CancellationToken)" />.
/// </summary>
public event EventHandler<DetectChangesEventArgs> DetectingChanges
{
add => ChangeDetector.DetectingChanges += value;
remove => ChangeDetector.DetectingChanges -= value;
}

/// <summary>
/// An event fired when any changes have been detected to the entity graph or a single entity, either through an
/// explicit call to <see cref="DetectChanges" /> or <see cref="EntityEntry.DetectChanges" />, or automatically, such as part of
/// executing <see cref="DbContext.SaveChanges()" /> or <see cref="DbContext.SaveChangesAsync(System.Threading.CancellationToken)" />.
/// </summary>
public event EventHandler<DetectedChangesEventArgs> DetectedChanges
{
add => ChangeDetector.DetectedChanges += value;
remove => ChangeDetector.DetectedChanges -= value;
}

/// <summary>
/// Forces immediate cascading deletion of child/dependent entities when they are either
/// severed from a required parent/principal entity, or the required parent/principal entity
Expand Down
39 changes: 39 additions & 0 deletions src/EFCore/ChangeTracking/DetectChangesEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;

namespace Microsoft.EntityFrameworkCore.ChangeTracking;

/// <summary>
/// Event arguments for the <see cref="ChangeTracker.DetectingChanges" /> event.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-state-changes">State changes of entities in EF Core</see> for more information and examples.
/// </remarks>
public class DetectChangesEventArgs : EventArgs
{
private readonly InternalEntityEntry? _internalEntityEntry;
private EntityEntry? _entry;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[EntityFrameworkInternal]
public DetectChangesEventArgs(InternalEntityEntry? internalEntityEntry)
{
_internalEntityEntry = internalEntityEntry;
}

/// <summary>
/// If detecting changes for a single entity, then this is the <see cref="EntityEntry" /> for that entity.
/// If detecting changes for an entire graph, then <see langword="null" />.
/// </summary>
public virtual EntityEntry? Entry
=> _internalEntityEntry == null
? null
: (_entry ??= new EntityEntry(_internalEntityEntry));
}
35 changes: 35 additions & 0 deletions src/EFCore/ChangeTracking/DetectedChangesEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;

namespace Microsoft.EntityFrameworkCore.ChangeTracking;

/// <summary>
/// Event arguments for the <see cref="ChangeTracker.DetectedChanges" /> event.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-state-changes">State changes of entities in EF Core</see> for more information and examples.
/// </remarks>
public class DetectedChangesEventArgs : DetectChangesEventArgs
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[EntityFrameworkInternal]
public DetectedChangesEventArgs(
InternalEntityEntry? internalEntityEntry,
bool changesFound)
: base(internalEntityEntry)
{
ChangesFound = changesFound;
}

/// <summary>
/// Returns <see langword="true" /> if changes were found, <see langword="false" /> otherwise.
/// </summary>
public virtual bool ChangesFound { get; }
}
42 changes: 42 additions & 0 deletions src/EFCore/ChangeTracking/EntityStateChangingEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;

namespace Microsoft.EntityFrameworkCore.ChangeTracking;

/// <summary>
/// Event arguments for the <see cref="ChangeTracker.StateChanging" /> event.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-state-changes">State changes of entities in EF Core</see> for more information and examples.
/// </remarks>
public class EntityStateChangingEventArgs : EntityEntryEventArgs
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[EntityFrameworkInternal]
public EntityStateChangingEventArgs(
InternalEntityEntry internalEntityEntry,
EntityState oldState,
EntityState newState)
: base(internalEntityEntry)
{
OldState = oldState;
NewState = newState;
}

/// <summary>
/// The state that the entity is transitioning from.
/// </summary>
public virtual EntityState OldState { get; }

/// <summary>
/// The state that the entity is transitioning to.
/// </summary>
public virtual EntityState NewState { get; }
}
42 changes: 42 additions & 0 deletions src/EFCore/ChangeTracking/EntityTrackingEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;

namespace Microsoft.EntityFrameworkCore.ChangeTracking;

/// <summary>
/// Event arguments for the <see cref="ChangeTracker.Tracking" /> event.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-state-changes">State changes of entities in EF Core</see> for more information and examples.
/// </remarks>
public class EntityTrackingEventArgs : EntityEntryEventArgs
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[EntityFrameworkInternal]
public EntityTrackingEventArgs(
InternalEntityEntry internalEntityEntry,
EntityState state,
bool fromQuery)
: base(internalEntityEntry)
{
State = state;
FromQuery = fromQuery;
}

/// <summary>
/// The <see cref="EntityState" /> that the tracked entity will be tracked with.
/// </summary>
public virtual EntityState State { get; }

/// <summary>
/// <see langword="true" /> if the entity is being tracked as part of a database query; <see langword="false" /> otherwise.
/// </summary>
public virtual bool FromQuery { get; }
}
Loading

0 comments on commit fa02b24

Please sign in to comment.