Skip to content

Commit

Permalink
Adjust DetectChanges events so they can be used to get a notification…
Browse files Browse the repository at this point in the history
… when all changes for an entity have been detected (#28356)
  • Loading branch information
ajcvickers authored Jul 1, 2022
1 parent 727b699 commit b121ee3
Show file tree
Hide file tree
Showing 13 changed files with 657 additions and 283 deletions.
54 changes: 46 additions & 8 deletions src/EFCore/ChangeTracking/ChangeTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -381,25 +381,63 @@ public event EventHandler<EntityStateChangedEventArgs> StateChanged
}

/// <summary>
/// An event fired when detecting changes to the entity graph or a single entity is about to happen, either through an
/// An event fired when detecting changes to 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
/// <remarks>
/// <see cref="AutoDetectChangesEnabled" /> is set to <see langword="false" /> for the duration of the event to prevent an infinite
/// loop of recursive automatic calls.
/// </remarks>
public event EventHandler<DetectEntityChangesEventArgs> DetectingEntityChanges
{
add => ChangeDetector.DetectingChanges += value;
remove => ChangeDetector.DetectingChanges -= value;
add => ChangeDetector.DetectingEntityChanges += value;
remove => ChangeDetector.DetectingEntityChanges -= value;
}

/// <summary>
/// An event fired when any changes have been detected to the entity graph or a single entity, either through an
/// An event fired when any changes have been detected to 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
/// <remarks>
/// <see cref="AutoDetectChangesEnabled" /> is set to <see langword="false" /> for the duration of the event to prevent an infinite
/// loop of recursive automatic calls.
/// </remarks>
public event EventHandler<DetectedEntityChangesEventArgs> DetectedEntityChanges
{
add => ChangeDetector.DetectedEntityChanges += value;
remove => ChangeDetector.DetectedEntityChanges -= value;
}

/// <summary>
/// An event fired when detecting changes to the entity graph about to happen, either through an
/// explicit call to <see cref="DetectChanges" />, or automatically, such as part of
/// executing <see cref="DbContext.SaveChanges()" /> or <see cref="DbContext.SaveChangesAsync(System.Threading.CancellationToken)" />.
/// </summary>
/// <remarks>
/// <see cref="AutoDetectChangesEnabled" /> is set to <see langword="false" /> for the duration of the event to prevent an infinite
/// loop of recursive automatic calls.
/// </remarks>
public event EventHandler<DetectChangesEventArgs> DetectingAllChanges
{
add => ChangeDetector.DetectingAllChanges += value;
remove => ChangeDetector.DetectingAllChanges -= value;
}

/// <summary>
/// An event fired when any changes have been detected to the entity graph, either through an
/// explicit call to <see cref="DetectChanges" />, or automatically, such as part of
/// executing <see cref="DbContext.SaveChanges()" /> or <see cref="DbContext.SaveChangesAsync(System.Threading.CancellationToken)" />.
/// </summary>
/// <remarks>
/// <see cref="AutoDetectChangesEnabled" /> is set to <see langword="false" /> for the duration of the event to prevent an infinite
/// loop of recursive automatic calls.
/// </remarks>
public event EventHandler<DetectedChangesEventArgs> DetectedAllChanges
{
add => ChangeDetector.DetectedChanges += value;
remove => ChangeDetector.DetectedChanges -= value;
add => ChangeDetector.DetectedAllChanges += value;
remove => ChangeDetector.DetectedAllChanges -= value;
}

/// <summary>
Expand Down
27 changes: 1 addition & 26 deletions src/EFCore/ChangeTracking/DetectChangesEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
// 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.
/// Event arguments for the <see cref="ChangeTracker.DetectingAllChanges" /> 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));
}
36 changes: 36 additions & 0 deletions src/EFCore/ChangeTracking/DetectEntityChangesEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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.DetectingEntityChanges" /> 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 DetectEntityChangesEventArgs : DetectChangesEventArgs
{
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 DetectEntityChangesEventArgs(InternalEntityEntry internalEntityEntry)
{
_internalEntityEntry = internalEntityEntry;
}

/// <summary>
/// The <see cref="EntityEntry" /> for the entity.
/// </summary>
public virtual EntityEntry Entry
=> _entry ??= new EntityEntry(_internalEntityEntry);
}
11 changes: 3 additions & 8 deletions src/EFCore/ChangeTracking/DetectedChangesEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
// 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.
/// Event arguments for the <see cref="ChangeTracker.DetectedAllChanges" /> 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
public class DetectedChangesEventArgs : EventArgs
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand All @@ -20,10 +18,7 @@ public class DetectedChangesEventArgs : DetectChangesEventArgs
/// 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)
public DetectedChangesEventArgs(bool changesFound)
{
ChangesFound = changesFound;
}
Expand Down
39 changes: 39 additions & 0 deletions src/EFCore/ChangeTracking/DetectedEntityChangesEventArgs.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.DetectedEntityChanges" /> 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 DetectedEntityChangesEventArgs : DetectedChangesEventArgs
{
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 DetectedEntityChangesEventArgs(
InternalEntityEntry internalEntityEntry,
bool changesFound)
: base(changesFound)
{
_internalEntityEntry = internalEntityEntry;
}

/// <summary>
/// The <see cref="EntityEntry" /> for the entity.
/// </summary>
public virtual EntityEntry Entry
=> _entry ??= new EntityEntry(_internalEntityEntry);
}
Loading

0 comments on commit b121ee3

Please sign in to comment.