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

Remove single query mode #17079

Merged
merged 1 commit into from
Aug 12, 2019
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
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// </summary>
void TrackedFromQuery(
[NotNull] InternalEntityEntry entry,
[CanBeNull] ISet<IForeignKey> handledForeignKeys);
void TrackedFromQuery([NotNull] InternalEntityEntry entry);

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
4 changes: 1 addition & 3 deletions src/EFCore/ChangeTracking/Internal/INavigationFixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// </summary>
void TrackedFromQuery(
[NotNull] InternalEntityEntry entry,
[CanBeNull] ISet<IForeignKey> handledForeignKeys);
void TrackedFromQuery([NotNull] InternalEntityEntry entry);

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
27 changes: 1 addition & 26 deletions src/EFCore/ChangeTracking/Internal/IStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,7 @@ public interface IStateManager : IResettableService
InternalEntityEntry StartTrackingFromQuery(
[NotNull] IEntityType baseEntityType,
[NotNull] object entity,
in ValueBuffer valueBuffer,
[CanBeNull] ISet<IForeignKey> handledForeignKeys);

/// <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>
void BeginTrackingQuery();
in ValueBuffer valueBuffer);

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down Expand Up @@ -375,22 +366,6 @@ IEnumerable<InternalEntityEntry> GetDependentsUsingRelationshipSnapshot(
/// </summary>
IEntityFinder CreateEntityFinder([NotNull] IEntityType entityType);

/// <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>
TrackingQueryMode GetTrackingQueryMode([NotNull] IEntityType entityType);

/// <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>
void EndSingleQueryMode();

/// <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
Expand Down
18 changes: 2 additions & 16 deletions src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
/// </summary>
public virtual void MarkUnchangedFromQuery([CanBeNull] ISet<IForeignKey> handledForeignKeys)
public virtual void MarkUnchangedFromQuery()
{
StateManager.InternalEntityEntryNotifier.StateChanging(this, EntityState.Unchanged);

Expand All @@ -389,15 +385,7 @@ public virtual void MarkUnchangedFromQuery([CanBeNull] ISet<IForeignKey> 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);
}

/// <summary>
Expand Down Expand Up @@ -506,8 +494,6 @@ public virtual void SetPropertyModified(
}
}

StateManager.EndSingleQueryMode();

if (changeState)
{
StateManager.ChangedCount++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// </summary>
public virtual void TrackedFromQuery(
InternalEntityEntry entry,
ISet<IForeignKey> handledForeignKeys)
=> _navigationFixer.TrackedFromQuery(entry, handledForeignKeys);
public virtual void TrackedFromQuery(InternalEntityEntry entry)
=> _navigationFixer.TrackedFromQuery(entry);

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
34 changes: 14 additions & 20 deletions src/EFCore/ChangeTracking/Internal/NavigationFixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// </summary>
public virtual void TrackedFromQuery(
InternalEntityEntry entry,
ISet<IForeignKey> handledForeignKeys)
InternalEntityEntry entry)
{
try
{
_inFixup = true;

InitialFixup(entry, handledForeignKeys, fromQuery: true);
InitialFixup(entry, fromQuery: true);
}
finally
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -574,38 +573,33 @@ private void DeleteFixup(InternalEntityEntry entry)

private void InitialFixup(
InternalEntityEntry entry,
ISet<IForeignKey> handledForeignKeys,
bool fromQuery)
{
var entityType = entry.EntityType;
var stateManager = entry.StateManager;

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)
Expand Down
67 changes: 2 additions & 65 deletions src/EFCore/ChangeTracking/Internal/StateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ private readonly EntityReferenceMap _entityReferenceMap
private IIdentityMap _identityMap1;
private Dictionary<IKey, IIdentityMap> _identityMaps;
private bool _needsUnsubscribe;
private bool _queryIsTracked;
private TrackingQueryMode _trackingQueryMode = TrackingQueryMode.Simple;
private IEntityType _singleQueryModeEntityType;

private readonly IDiagnosticsLogger<DbLoggerCategory.ChangeTracking> _changeTrackingLogger;
private readonly IInternalEntityEntryFactory _internalEntityEntryFactory;
Expand Down Expand Up @@ -125,38 +122,6 @@ public StateManager([NotNull] StateManagerDependencies dependencies)
/// </summary>
public virtual CascadeTiming CascadeDeleteTiming { get; set; } = CascadeTiming.Immediate;

/// <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>
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;
}

/// <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>
public virtual void EndSingleQueryMode() => _trackingQueryMode = TrackingQueryMode.Multiple;

/// <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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -305,8 +266,6 @@ public virtual InternalEntityEntry GetOrCreateEntry(object entity, IEntityType e
/// </summary>
public virtual InternalEntityEntry CreateEntry(IDictionary<string, object> values, IEntityType entityType)
{
_trackingQueryMode = TrackingQueryMode.Multiple;

var (i, j) = (0, 0);
var valuesArray = new object[entityType.PropertyCount()];
var shadowPropertyValuesArray = new object[entityType.ShadowPropertyCount()];
Expand Down Expand Up @@ -357,24 +316,6 @@ private void UpdateReferenceMaps(
_entityReferenceMap.Update(entry, state, oldState);
}

/// <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>
public virtual void BeginTrackingQuery()
{
if (_queryIsTracked)
{
_trackingQueryMode = TrackingQueryMode.Multiple;
}
else
{
_queryIsTracked = true;
}
}

/// <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
Expand All @@ -384,8 +325,7 @@ public virtual void BeginTrackingQuery()
public virtual InternalEntityEntry StartTrackingFromQuery(
IEntityType baseEntityType,
object entity,
in ValueBuffer valueBuffer,
ISet<IForeignKey> handledForeignKeys)
in ValueBuffer valueBuffer)
{
var existingEntry = TryGetEntry(entity);
if (existingEntry != null)
Expand All @@ -410,7 +350,7 @@ public virtual InternalEntityEntry StartTrackingFromQuery(

UpdateReferenceMaps(newEntry, EntityState.Unchanged, null);

newEntry.MarkUnchangedFromQuery(handledForeignKeys);
newEntry.MarkUnchangedFromQuery();

if (_internalEntityEntrySubscriber.SnapshotAndSubscribe(newEntry))
{
Expand Down Expand Up @@ -711,9 +651,6 @@ public virtual void ResetState()
_identityMap1?.Clear();

_needsUnsubscribe = false;
_queryIsTracked = false;
_trackingQueryMode = TrackingQueryMode.Simple;
_singleQueryModeEntityType = null;

Tracked = null;
StateChanged = null;
Expand Down
53 changes: 0 additions & 53 deletions src/EFCore/ChangeTracking/Internal/TrackingQueryMode.cs

This file was deleted.

Loading