Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust DetectChanges events so they can be used to get a notification when all changes for an entity have been detected #28356

Merged
merged 1 commit into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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