Skip to content

Commit

Permalink
Change tracker docs
Browse files Browse the repository at this point in the history
Fixes #2725
Fixes #2707
Fixes #2525
Fixes #2524
Fixes #2331
Fixes #2105
Fixes #2076
Fixes #1541
Fixes #1489
Fixes #1453
Fixes #1398
Fixes #1339
Fixes #1235
Fixes #1007
Fixes #863
Fixes #815
Fixes #786
Fixes #531
Fixes #505
  • Loading branch information
ajcvickers committed Dec 31, 2020
1 parent a67d5c9 commit 1610216
Show file tree
Hide file tree
Showing 8 changed files with 1,084 additions and 911 deletions.
7 changes: 7 additions & 0 deletions entity-framework/core/change-tracking/change-detection.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,10 @@ EF Core creates proxy instances automatically when querying the database, so thi
Console.WriteLine(context.ChangeTracker.DebugView.LongView);
-->
[!code-csharp[Change_tracking_proxies_1](../../../samples/core/ChangeTracking/ChangeDetectionAndNotifications/ChangeTrackingProxiesSamples.cs?name=Change_tracking_proxies_1)]

## Change tracking events

EF Core fires the <xref:Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.Tracked?displayProperty=nameWithType> event when an entity is tracked for the first time. Future entity state changes result in an <xref:Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.StateChanged?displayProperty=nameWithType> event. See [.NET Events in EF Core](xref:core/logging-events-diagnostics/events) for more information.

> [!NOTE]
> The `StateChanged` event is not fired when an entity is first tracked, even though the state changes from `Detached` to something else when this happens. Make sure to listen for both `StateChanged` and `Tracked` events to get all relevant notifications.
1,000 changes: 1,000 additions & 0 deletions entity-framework/core/change-tracking/explicit-tracking.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions entity-framework/core/change-tracking/identity-resolution.md
Original file line number Diff line number Diff line change
Expand Up @@ -659,3 +659,7 @@ This comparer can then be used when creating collection navigations. For example
= new HashSet<Order>(ReferenceEqualityComparer.Instance);
-->
[!code-csharp[OrdersCollection](../../../samples/core/ChangeTracking/IdentityResolutionInEFCore/IdentityResolutionSamples.cs?name=OrdersCollection)]

### Comparing key properties

In addition to equality comparisons, key values also need to be ordered. This is important for avoiding deadlocks when updating multiple entities in a single call to SaveChanges. All types used for primary, alternate, or foreign key properties must implement <xref:System.IComparable%601> and <xref:System.IEquatable%601>. All types normally used as keys (int, Guid, string, etc.) already support these interfaces.
913 changes: 4 additions & 909 deletions entity-framework/core/change-tracking/index.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions entity-framework/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@
items:
- name: Overview
href: core/change-tracking/index.md
- name: Explicitly tracking entities
href: core/change-tracking/explicit-tracking.md
- name: Accessing tracked entities
href: core/change-tracking/entity-entries.md
- name: Changing foreign keys and navigations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,69 @@ public static void Updating_existing_entities_3()

Console.WriteLine();
}

public static void Custom_tracking_with_TrackGraph_1()
{
Console.WriteLine($">>>> Sample: {nameof(Custom_tracking_with_TrackGraph_1)}");
Console.WriteLine();

Helpers.RecreateCleanDatabase();
Helpers.PopulateDatabase();

using var context = new BlogsContext();

var blog = context.Blogs.AsNoTracking().Include(e => e.Posts).Single(e => e.Name == ".NET Blog");

#region Custom_tracking_with_TrackGraph_1a
blog.Posts.Add(
new Post
{
Title = "Announcing .NET 5.0",
Content = ".NET 5.0 includes many enhancements, including single file applications, more..."
}
);

var toDelete = blog.Posts.Single(e => e.Title == "Announcing F# 5");
toDelete.Id = -toDelete.Id;
#endregion

UpdateBlog(blog);

Console.WriteLine();
}

#region Custom_tracking_with_TrackGraph_1b
public static void UpdateBlog(Blog blog)
{
using var context = new BlogsContext();

context.ChangeTracker.TrackGraph(
blog, node =>
{
var propertyEntry = node.Entry.Property("Id");
var keyValue = (int)propertyEntry.CurrentValue;
if (keyValue == 0)
{
node.Entry.State = EntityState.Added;
}
else if (keyValue < 0)
{
propertyEntry.CurrentValue = -keyValue;
node.Entry.State = EntityState.Deleted;
}
else
{
node.Entry.State = EntityState.Modified;
}
Console.WriteLine($"Tracking {node.Entry.Metadata.DisplayName()} with key value {keyValue} as {node.Entry.State}");
});

context.SaveChanges();
}
#endregion
}

public static class Helpers
Expand Down
2 changes: 2 additions & 0 deletions samples/core/ChangeTracking/ChangeTrackingInEFCore/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,7 @@ public static void Main()
ExplicitKeysSamples.Deleting_dependent_child_entities_2();
ExplicitKeysSamples.Deleting_principal_parent_entities_1();
ExplicitKeysRequiredSamples.Deleting_principal_parent_entities_1();

GeneratedKeysSamples.Custom_tracking_with_TrackGraph_1();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,13 @@ public static void UpdatePostsFromJsonWithIdentityResolution(string json)
if (existingEntity == null)
{
Console.WriteLine($"Tracking {entityType} entity with key value {keyValue}");
Console.WriteLine($"Tracking {entityType.DisplayName()} entity with key value {keyValue}");
node.Entry.State = EntityState.Modified;
}
else
{
Console.WriteLine($"Discarding duplicate {entityType} entity with key value {keyValue}");
Console.WriteLine($"Discarding duplicate {entityType.DisplayName()} entity with key value {keyValue}");
}
});
}
Expand Down

0 comments on commit 1610216

Please sign in to comment.