diff --git a/src/EFCore/ChangeTracking/Internal/IInternalEntityEntryNotifier.cs b/src/EFCore/ChangeTracking/Internal/IInternalEntityEntryNotifier.cs index 728cda981b2..1c6d7617c90 100644 --- a/src/EFCore/ChangeTracking/Internal/IInternalEntityEntryNotifier.cs +++ b/src/EFCore/ChangeTracking/Internal/IInternalEntityEntryNotifier.cs @@ -46,9 +46,7 @@ public interface IInternalEntityEntryNotifier /// 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. /// - void TrackedFromQuery( - [NotNull] InternalEntityEntry entry, - [CanBeNull] ISet handledForeignKeys); + void TrackedFromQuery([NotNull] InternalEntityEntry entry); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/ChangeTracking/Internal/INavigationFixer.cs b/src/EFCore/ChangeTracking/Internal/INavigationFixer.cs index 4343261a430..b962856a691 100644 --- a/src/EFCore/ChangeTracking/Internal/INavigationFixer.cs +++ b/src/EFCore/ChangeTracking/Internal/INavigationFixer.cs @@ -54,9 +54,7 @@ void NavigationCollectionChanged( /// 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. /// - void TrackedFromQuery( - [NotNull] InternalEntityEntry entry, - [CanBeNull] ISet handledForeignKeys); + void TrackedFromQuery([NotNull] InternalEntityEntry entry); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/ChangeTracking/Internal/IStateManager.cs b/src/EFCore/ChangeTracking/Internal/IStateManager.cs index bccb5c48a5d..37981dfd552 100644 --- a/src/EFCore/ChangeTracking/Internal/IStateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/IStateManager.cs @@ -90,16 +90,7 @@ public interface IStateManager : IResettableService InternalEntityEntry StartTrackingFromQuery( [NotNull] IEntityType baseEntityType, [NotNull] object entity, - in ValueBuffer valueBuffer, - [CanBeNull] ISet handledForeignKeys); - - /// - /// 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. - /// - void BeginTrackingQuery(); + in ValueBuffer valueBuffer); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -375,22 +366,6 @@ IEnumerable GetDependentsUsingRelationshipSnapshot( /// IEntityFinder CreateEntityFinder([NotNull] IEntityType entityType); - /// - /// 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. - /// - TrackingQueryMode GetTrackingQueryMode([NotNull] IEntityType entityType); - - /// - /// 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. - /// - void EndSingleQueryMode(); - /// /// 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 diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index e5368ae3dab..1106128e328 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -209,8 +209,6 @@ private bool PrepareForAdd(EntityState newState) // can happen without constraints on changing read-only values kicking in _stateData.EntityState = EntityState.Detached; - StateManager.EndSingleQueryMode(); - return true; } @@ -251,8 +249,6 @@ private void SetEntityState(EntityState oldState, EntityState newState, bool acc _stateData.FlagProperty(property.GetIndex(), PropertyFlag.Modified, isFlagged: false); } } - - StateManager.EndSingleQueryMode(); } if (oldState == newState) @@ -379,7 +375,7 @@ private void SetServiceProperties(EntityState oldState, EntityState newState) /// 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. /// - public virtual void MarkUnchangedFromQuery([CanBeNull] ISet handledForeignKeys) + public virtual void MarkUnchangedFromQuery() { StateManager.InternalEntityEntryNotifier.StateChanging(this, EntityState.Unchanged); @@ -389,15 +385,7 @@ public virtual void MarkUnchangedFromQuery([CanBeNull] ISet handled StateManager.OnTracked(this, fromQuery: true); - var trackingQueryMode = StateManager.GetTrackingQueryMode(EntityType); - if (trackingQueryMode != TrackingQueryMode.Simple) - { - StateManager.InternalEntityEntryNotifier.TrackedFromQuery( - this, - trackingQueryMode == TrackingQueryMode.Single - ? handledForeignKeys - : null); - } + StateManager.InternalEntityEntryNotifier.TrackedFromQuery(this); } /// @@ -506,8 +494,6 @@ public virtual void SetPropertyModified( } } - StateManager.EndSingleQueryMode(); - if (changeState) { StateManager.ChangedCount++; diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntryNotifier.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntryNotifier.cs index b1daacd50fe..cf55d105958 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntryNotifier.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntryNotifier.cs @@ -74,10 +74,8 @@ public virtual void StateChanged(InternalEntityEntry entry, EntityState oldState /// 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. /// - public virtual void TrackedFromQuery( - InternalEntityEntry entry, - ISet handledForeignKeys) - => _navigationFixer.TrackedFromQuery(entry, handledForeignKeys); + public virtual void TrackedFromQuery(InternalEntityEntry entry) + => _navigationFixer.TrackedFromQuery(entry); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs b/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs index c21b6b8537d..d81c5c620dd 100644 --- a/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs +++ b/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs @@ -474,14 +474,13 @@ public virtual void StateChanging(InternalEntityEntry entry, EntityState newStat /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual void TrackedFromQuery( - InternalEntityEntry entry, - ISet handledForeignKeys) + InternalEntityEntry entry) { try { _inFixup = true; - InitialFixup(entry, handledForeignKeys, fromQuery: true); + InitialFixup(entry, fromQuery: true); } finally { @@ -511,7 +510,7 @@ public virtual void StateChanged( if (oldState == EntityState.Detached) { - InitialFixup(entry, null, fromQuery: false); + InitialFixup(entry, fromQuery: false); } else if (entry.EntityState == EntityState.Detached) { @@ -574,7 +573,6 @@ private void DeleteFixup(InternalEntityEntry entry) private void InitialFixup( InternalEntityEntry entry, - ISet handledForeignKeys, bool fromQuery) { var entityType = entry.EntityType; @@ -582,30 +580,26 @@ private void InitialFixup( foreach (var foreignKey in entityType.GetForeignKeys()) { - if (handledForeignKeys?.Contains(foreignKey) != true) + var principalEntry = stateManager.FindPrincipal(entry, foreignKey); + if (principalEntry != null) { - var principalEntry = stateManager.FindPrincipal(entry, foreignKey); - if (principalEntry != null) + var navigation = foreignKey.DependentToPrincipal; + var existingPrincipal = navigation == null ? null : entry[navigation]; + if (existingPrincipal == null + || existingPrincipal == principalEntry.Entity) { - var navigation = foreignKey.DependentToPrincipal; - var existingPrincipal = navigation == null ? null : entry[navigation]; - if (existingPrincipal == null - || existingPrincipal == principalEntry.Entity) - { - // Set navigation to principal based on FK properties - SetNavigation(entry, navigation, principalEntry, fromQuery); + // Set navigation to principal based on FK properties + SetNavigation(entry, navigation, principalEntry, fromQuery); - // Add this entity to principal's collection, or set inverse for 1:1 - ToDependentFixup(entry, principalEntry, foreignKey, fromQuery); - } + // Add this entity to principal's collection, or set inverse for 1:1 + ToDependentFixup(entry, principalEntry, foreignKey, fromQuery); } } } foreach (var foreignKey in entityType.GetReferencingForeignKeys()) { - if (foreignKey.DeclaringEntityType.FindPrimaryKey() != null - && handledForeignKeys?.Contains(foreignKey) != true) + if (foreignKey.DeclaringEntityType.FindPrimaryKey() != null) { var dependents = stateManager.GetDependents(entry, foreignKey); if (foreignKey.IsUnique) diff --git a/src/EFCore/ChangeTracking/Internal/StateManager.cs b/src/EFCore/ChangeTracking/Internal/StateManager.cs index 36acdcbb0eb..07183b24343 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManager.cs @@ -44,9 +44,6 @@ private readonly EntityReferenceMap _entityReferenceMap private IIdentityMap _identityMap1; private Dictionary _identityMaps; private bool _needsUnsubscribe; - private bool _queryIsTracked; - private TrackingQueryMode _trackingQueryMode = TrackingQueryMode.Simple; - private IEntityType _singleQueryModeEntityType; private readonly IDiagnosticsLogger _changeTrackingLogger; private readonly IInternalEntityEntryFactory _internalEntityEntryFactory; @@ -125,38 +122,6 @@ public StateManager([NotNull] StateManagerDependencies dependencies) /// public virtual CascadeTiming CascadeDeleteTiming { get; set; } = CascadeTiming.Immediate; - /// - /// 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. - /// - public virtual TrackingQueryMode GetTrackingQueryMode(IEntityType entityType) - { - if (_trackingQueryMode == TrackingQueryMode.Simple - && _singleQueryModeEntityType != entityType) - { - // Drop out if SQM for change of entity type or self-refs since query may not fix them up. - if (_singleQueryModeEntityType != null - || entityType.GetNavigations().Any(n => entityType.IsSameHierarchy(n.GetTargetType()))) - { - _trackingQueryMode = TrackingQueryMode.Single; - } - - _singleQueryModeEntityType = entityType; - } - - return _trackingQueryMode; - } - - /// - /// 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. - /// - public virtual void EndSingleQueryMode() => _trackingQueryMode = TrackingQueryMode.Multiple; - /// /// 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 @@ -229,8 +194,6 @@ public virtual InternalEntityEntry GetOrCreateEntry(object entity) var entry = TryGetEntry(entity); if (entry == null) { - _trackingQueryMode = TrackingQueryMode.Multiple; - var entityType = _model.FindRuntimeEntityType(entity.GetType()); if (entityType == null) { @@ -271,8 +234,6 @@ public virtual InternalEntityEntry GetOrCreateEntry(object entity, IEntityType e var entry = TryGetEntry(entity, entityType); if (entry == null) { - _trackingQueryMode = TrackingQueryMode.Multiple; - var runtimeEntityType = _model.FindRuntimeEntityType(entity.GetType()); if (runtimeEntityType != null) { @@ -305,8 +266,6 @@ public virtual InternalEntityEntry GetOrCreateEntry(object entity, IEntityType e /// public virtual InternalEntityEntry CreateEntry(IDictionary values, IEntityType entityType) { - _trackingQueryMode = TrackingQueryMode.Multiple; - var (i, j) = (0, 0); var valuesArray = new object[entityType.PropertyCount()]; var shadowPropertyValuesArray = new object[entityType.ShadowPropertyCount()]; @@ -357,24 +316,6 @@ private void UpdateReferenceMaps( _entityReferenceMap.Update(entry, state, oldState); } - /// - /// 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. - /// - public virtual void BeginTrackingQuery() - { - if (_queryIsTracked) - { - _trackingQueryMode = TrackingQueryMode.Multiple; - } - else - { - _queryIsTracked = true; - } - } - /// /// 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 @@ -384,8 +325,7 @@ public virtual void BeginTrackingQuery() public virtual InternalEntityEntry StartTrackingFromQuery( IEntityType baseEntityType, object entity, - in ValueBuffer valueBuffer, - ISet handledForeignKeys) + in ValueBuffer valueBuffer) { var existingEntry = TryGetEntry(entity); if (existingEntry != null) @@ -410,7 +350,7 @@ public virtual InternalEntityEntry StartTrackingFromQuery( UpdateReferenceMaps(newEntry, EntityState.Unchanged, null); - newEntry.MarkUnchangedFromQuery(handledForeignKeys); + newEntry.MarkUnchangedFromQuery(); if (_internalEntityEntrySubscriber.SnapshotAndSubscribe(newEntry)) { @@ -711,9 +651,6 @@ public virtual void ResetState() _identityMap1?.Clear(); _needsUnsubscribe = false; - _queryIsTracked = false; - _trackingQueryMode = TrackingQueryMode.Simple; - _singleQueryModeEntityType = null; Tracked = null; StateChanged = null; diff --git a/src/EFCore/ChangeTracking/Internal/TrackingQueryMode.cs b/src/EFCore/ChangeTracking/Internal/TrackingQueryMode.cs deleted file mode 100644 index 11d51f3e95e..00000000000 --- a/src/EFCore/ChangeTracking/Internal/TrackingQueryMode.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal -{ - /// - /// 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. - /// - public enum TrackingQueryMode - { - /// - /// - /// 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. - /// - /// - /// The state manager is tracking for a single query for one entity type and no self-refs. - /// - /// - Simple, - - /// - /// - /// 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. - /// - /// - /// The state manager is tracking for a single query, but with multiple entity types and/or self refs. - /// - /// - Single, - - /// - /// - /// 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. - /// - /// - /// The state manager is tracking for multiple queries and/or with other tracked entities. - /// - /// - Multiple - } -} diff --git a/src/EFCore/Query/QueryContext.cs b/src/EFCore/Query/QueryContext.cs index d2c06d2819f..643aa2da773 100644 --- a/src/EFCore/Query/QueryContext.cs +++ b/src/EFCore/Query/QueryContext.cs @@ -150,15 +150,10 @@ public virtual object Remove(string name) return value; } - /// - /// Notify the state manager that a tracking query is starting. - /// - public virtual void BeginTrackingQuery() => StateManager.BeginTrackingQuery(); - public virtual InternalEntityEntry StartTracking( IEntityType entityType, object entity, ValueBuffer valueBuffer) - => StateManager.StartTrackingFromQuery(entityType, entity, valueBuffer, handledForeignKeys: null); + => StateManager.StartTrackingFromQuery(entityType, entity, valueBuffer); } } diff --git a/test/EFCore.Tests/ChangeTracking/Internal/FixupTest.cs b/test/EFCore.Tests/ChangeTracking/Internal/FixupTest.cs index 345e64a70e7..28b9e8fed9c 100644 --- a/test/EFCore.Tests/ChangeTracking/Internal/FixupTest.cs +++ b/test/EFCore.Tests/ChangeTracking/Internal/FixupTest.cs @@ -2508,36 +2508,30 @@ public void Navigation_fixup_happens_when_entities_are_tracked_from_query() var stateManager = context.GetService(); - stateManager.BeginTrackingQuery(); + stateManager.StartTrackingFromQuery(categoryType, new Category(11), new ValueBuffer(new object[] { 11 })); + stateManager.StartTrackingFromQuery(categoryType, new Category(12), new ValueBuffer(new object[] { 12 })); + stateManager.StartTrackingFromQuery(categoryType, new Category(13), new ValueBuffer(new object[] { 13 })); - stateManager.StartTrackingFromQuery(categoryType, new Category(11), new ValueBuffer(new object[] { 11 }), null); - stateManager.StartTrackingFromQuery(categoryType, new Category(12), new ValueBuffer(new object[] { 12 }), null); - stateManager.StartTrackingFromQuery(categoryType, new Category(13), new ValueBuffer(new object[] { 13 }), null); - - stateManager.BeginTrackingQuery(); - - stateManager.StartTrackingFromQuery(productType, new Product(21, 11), new ValueBuffer(new object[] { 21, 11 }), null); + stateManager.StartTrackingFromQuery(productType, new Product(21, 11), new ValueBuffer(new object[] { 21, 11 })); AssertAllFixedUp(context); - stateManager.StartTrackingFromQuery(productType, new Product(22, 11), new ValueBuffer(new object[] { 22, 11 }), null); + stateManager.StartTrackingFromQuery(productType, new Product(22, 11), new ValueBuffer(new object[] { 22, 11 })); AssertAllFixedUp(context); - stateManager.StartTrackingFromQuery(productType, new Product(23, 11), new ValueBuffer(new object[] { 23, 11 }), null); + stateManager.StartTrackingFromQuery(productType, new Product(23, 11), new ValueBuffer(new object[] { 23, 11 })); AssertAllFixedUp(context); - stateManager.StartTrackingFromQuery(productType, new Product(24, 12), new ValueBuffer(new object[] { 24, 12 }), null); + stateManager.StartTrackingFromQuery(productType, new Product(24, 12), new ValueBuffer(new object[] { 24, 12 })); AssertAllFixedUp(context); - stateManager.StartTrackingFromQuery(productType, new Product(25, 12), new ValueBuffer(new object[] { 25, 12 }), null); + stateManager.StartTrackingFromQuery(productType, new Product(25, 12), new ValueBuffer(new object[] { 25, 12 })); AssertAllFixedUp(context); - stateManager.BeginTrackingQuery(); - - stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(31, 22), new ValueBuffer(new object[] { 31, 22 }), null); + stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(31, 22), new ValueBuffer(new object[] { 31, 22 })); AssertAllFixedUp(context); - stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(32, 22), new ValueBuffer(new object[] { 32, 22 }), null); + stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(32, 22), new ValueBuffer(new object[] { 32, 22 })); AssertAllFixedUp(context); - stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(33, 24), new ValueBuffer(new object[] { 33, 24 }), null); + stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(33, 24), new ValueBuffer(new object[] { 33, 24 })); AssertAllFixedUp(context); - stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(34, 24), new ValueBuffer(new object[] { 34, 24 }), null); + stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(34, 24), new ValueBuffer(new object[] { 34, 24 })); AssertAllFixedUp(context); - stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(35, 24), new ValueBuffer(new object[] { 35, 24 }), null); + stateManager.StartTrackingFromQuery(offerType, new SpecialOffer(35, 24), new ValueBuffer(new object[] { 35, 24 })); AssertAllFixedUp(context); diff --git a/test/EFCore.Tests/ChangeTracking/Internal/InternalEntryEntrySubscriberTest.cs b/test/EFCore.Tests/ChangeTracking/Internal/InternalEntryEntrySubscriberTest.cs index 375552833df..a018326c86e 100644 --- a/test/EFCore.Tests/ChangeTracking/Internal/InternalEntryEntrySubscriberTest.cs +++ b/test/EFCore.Tests/ChangeTracking/Internal/InternalEntryEntrySubscriberTest.cs @@ -542,7 +542,7 @@ public void NavigationCollectionChanged( InternalEntityEntry entry, INavigation navigation, IEnumerable added, IEnumerable removed) => CollectionChanged.Add(Tuple.Create(entry, navigation, added, removed)); - public void TrackedFromQuery(InternalEntityEntry entry, ISet handledForeignKeys) + public void TrackedFromQuery(InternalEntityEntry entry) { } diff --git a/test/EFCore.Tests/ChangeTracking/Internal/StateManagerTest.cs b/test/EFCore.Tests/ChangeTracking/Internal/StateManagerTest.cs index 2e3270f9023..8f386150d69 100644 --- a/test/EFCore.Tests/ChangeTracking/Internal/StateManagerTest.cs +++ b/test/EFCore.Tests/ChangeTracking/Internal/StateManagerTest.cs @@ -6,7 +6,6 @@ using System.Linq; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.TestUtilities; using Microsoft.Extensions.DependencyInjection; @@ -395,9 +394,9 @@ public void StartTracking_is_no_op_if_entity_is_already_tracked() }; var valueBuffer = new ValueBuffer(new object[] { 77, "Bjork", 777 }); - var entry = stateManager.StartTrackingFromQuery(categoryType, category, valueBuffer, null); + var entry = stateManager.StartTrackingFromQuery(categoryType, category, valueBuffer); - Assert.Same(entry, stateManager.StartTrackingFromQuery(categoryType, category, valueBuffer, null)); + Assert.Same(entry, stateManager.StartTrackingFromQuery(categoryType, category, valueBuffer)); } [ConditionalFact] @@ -437,210 +436,6 @@ public void StartTracking_throws_for_invalid_alternate_key() () => stateManager.StartTracking(entry)).Message); } - [ConditionalFact] - public void State_manager_switches_out_of_single_query_mode_when_second_query_begins() - { - var model = BuildModel(); - var categoryType = model.FindEntityType(typeof(Category)); - var stateManager = CreateStateManager(model); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.BeginTrackingQuery(); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.StartTrackingFromQuery( - categoryType, - new Category - { - Id = 77, - PrincipalId = 777 - }, - new ValueBuffer(new object[] { 77, "Bjork", 777 }), null); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.StartTrackingFromQuery( - categoryType, - new Category - { - Id = 78, - PrincipalId = 778 - }, - new ValueBuffer(new object[] { 78, "Beck", 778 }), null); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.BeginTrackingQuery(); - - Assert.Equal(TrackingQueryMode.Multiple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.StartTrackingFromQuery( - categoryType, - new Category - { - Id = 79, - PrincipalId = 779 - }, - new ValueBuffer(new object[] { 79, "Bush", 779 }), null); - - Assert.Equal(TrackingQueryMode.Multiple, stateManager.GetTrackingQueryMode(categoryType)); - } - - [ConditionalFact] - public void State_manager_switches_out_of_single_query_mode_when_entity_has_self_refs() - { - var model = BuildModel(); - var widgetType = model.FindEntityType(typeof(Widget)); - var stateManager = CreateStateManager(model); - - Assert.Equal(TrackingQueryMode.Single, stateManager.GetTrackingQueryMode(widgetType)); - - stateManager.BeginTrackingQuery(); - - Assert.Equal(TrackingQueryMode.Single, stateManager.GetTrackingQueryMode(widgetType)); - } - - [ConditionalFact] - public void State_manager_switches_out_of_single_query_mode_when_entity_included() - { - var model = BuildModel(); - var productType = model.FindEntityType(typeof(Product)); - var categoryType = model.FindEntityType(typeof(Category)); - var stateManager = CreateStateManager(model); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.BeginTrackingQuery(); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - Assert.Equal(TrackingQueryMode.Single, stateManager.GetTrackingQueryMode(productType)); - - Assert.Equal(TrackingQueryMode.Single, stateManager.GetTrackingQueryMode(categoryType)); - } - - [ConditionalFact] - public void State_manager_switches_out_of_single_query_mode_when_tracked_state_changes_to_Modified() - { - var model = BuildModel(); - var categoryType = model.FindEntityType(typeof(Category)); - var stateManager = CreateStateManager(model); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.BeginTrackingQuery(); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.StartTrackingFromQuery( - categoryType, - new Category - { - Id = 77, - PrincipalId = 777 - }, - new ValueBuffer(new object[] { 77, "Bjork", 777 }), null); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - var entry = stateManager.StartTrackingFromQuery( - categoryType, - new Category - { - Id = 78, - PrincipalId = 778 - }, - new ValueBuffer(new object[] { 78, "Beck", 778 }), null); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - entry.SetEntityState(EntityState.Modified); - - Assert.Equal(TrackingQueryMode.Multiple, stateManager.GetTrackingQueryMode(categoryType)); - } - - [ConditionalFact] - public void State_manager_switches_out_of_single_query_mode_when_tracked_state_changes_to_Added() - { - var model = BuildModel(); - var categoryType = model.FindEntityType(typeof(Category)); - var stateManager = CreateStateManager(model); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.BeginTrackingQuery(); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.StartTrackingFromQuery( - categoryType, - new Category - { - Id = 77, - PrincipalId = 777 - }, - new ValueBuffer(new object[] { 77, "Bjork", null }), null); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - var entry = stateManager.StartTrackingFromQuery( - categoryType, - new Category - { - Id = 78, - PrincipalId = 778 - }, - new ValueBuffer(new object[] { 78, "Beck", 778 }), null); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - entry.SetEntityState(EntityState.Added); - - Assert.Equal(TrackingQueryMode.Multiple, stateManager.GetTrackingQueryMode(categoryType)); - } - - [ConditionalFact] - public void State_manager_does_not_switch_out_of_single_query_mode_when_getting_existing_entry() - { - var model = BuildModel(); - var categoryType = model.FindEntityType(typeof(Category)); - var stateManager = CreateStateManager(model); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.BeginTrackingQuery(); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - var entry = stateManager.StartTrackingFromQuery( - categoryType, - new Category - { - Id = 77, - PrincipalId = 777 - }, - new ValueBuffer(new object[] { 77, "Bjork", 777 }), null); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.StartTrackingFromQuery( - categoryType, - new Category - { - Id = 78, - PrincipalId = 778 - }, - new ValueBuffer(new object[] { 78, "Beck", 778 }), null); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - - stateManager.GetOrCreateEntry(entry.Entity); - - Assert.Equal(TrackingQueryMode.Simple, stateManager.GetTrackingQueryMode(categoryType)); - } - [ConditionalFact] public void Can_get_existing_entry_even_if_state_not_yet_set() { @@ -840,7 +635,7 @@ public void NavigationCollectionChanged(InternalEntityEntry entry, INavigation n { } - public void TrackedFromQuery(InternalEntityEntry entry, ISet handledForeignKeys) + public void TrackedFromQuery(InternalEntityEntry entry) { } diff --git a/test/EFCore.Tests/DbContextServicesTest.cs b/test/EFCore.Tests/DbContextServicesTest.cs index 20f6d89e1bc..34ed107ce9e 100644 --- a/test/EFCore.Tests/DbContextServicesTest.cs +++ b/test/EFCore.Tests/DbContextServicesTest.cs @@ -408,7 +408,7 @@ public void KeyPropertyChanged( InternalEntityEntry entry, IProperty property, IReadOnlyList containingPrincipalKeys, IReadOnlyList containingForeignKeys, object oldValue, object newValue) => throw new NotImplementedException(); - public void TrackedFromQuery(InternalEntityEntry entry, ISet handledForeignKeys) => + public void TrackedFromQuery(InternalEntityEntry entry) => throw new NotImplementedException(); } diff --git a/test/EFCore.Tests/TestUtilities/FakeStateManager.cs b/test/EFCore.Tests/TestUtilities/FakeStateManager.cs index 7cf3e9f8a9c..79d71acd7da 100644 --- a/test/EFCore.Tests/TestUtilities/FakeStateManager.cs +++ b/test/EFCore.Tests/TestUtilities/FakeStateManager.cs @@ -24,12 +24,6 @@ public class FakeStateManager : IStateManager public bool SaveChangesCalled { get; set; } public bool SaveChangesAsyncCalled { get; set; } - public TrackingQueryMode GetTrackingQueryMode(IEntityType entityType) => TrackingQueryMode.Multiple; - - public void EndSingleQueryMode() - { - } - public void ResetState() { } @@ -101,7 +95,7 @@ public InternalEntityEntry CreateEntry(IDictionary values, IEnti throw new NotImplementedException(); public InternalEntityEntry StartTrackingFromQuery( - IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer, ISet handledForeignKeys) => + IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) => throw new NotImplementedException(); public void BeginTrackingQuery() => throw new NotImplementedException();