Skip to content

Update snapshots when a shared-identity entry is added #26076

@AndriySvyryd

Description

@AndriySvyryd

This will allow to remove extra logic for handling original values from the Update pipeline.

Add to InternalEntityEntry.HandleSharedIdentityEntry:

if (oldState == EntityState.Detached
	&& (newState == EntityState.Added
		|| newState == EntityState.Modified))
{
	var commonType = entityType.FindClosestCommonParent(sharedIdentityEntry.EntityType)!;
	if (commonType.UseEagerSnapshots())
	{
		foreach (var property in commonType.GetProperties())
		{
			if (property.GetOriginalValueIndex() >= 0)
			{
				SetOriginalValue(property, sharedIdentityEntry.GetOriginalValue(property));
			}
		}

		var changeDetector = (StateManager as StateManager)?.ChangeDetector as ChangeDetector;

		foreach (var navigation in entityType.GetNavigations())
		{
			if (navigation.GetRelationshipIndex() >= 0)
			{
				SetRelationshipSnapshotValue(navigation, sharedIdentityEntry.GetRelationshipSnapshotValue(navigation));

				changeDetector?.DetectNavigationChange(this, navigation);
			}
		}

		foreach (var navigation in entityType.GetSkipNavigations())
		{
			if (navigation.GetRelationshipIndex() >= 0)
			{
				SetRelationshipSnapshotValue(navigation, sharedIdentityEntry.GetRelationshipSnapshotValue(navigation));

				changeDetector?.DetectNavigationChange(this, navigation);
			}
		}
	}
}
/// <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 void SetRelationshipSnapshotValue(INavigationBase navigation, object? value)
{
	EnsureRelationshipSnapshot();

	if (navigation.IsCollection)
	{
		var currentSnapshotCollection = (IEnumerable?)_relationshipsSnapshot.GetValue(this, navigation);
		if (currentSnapshotCollection != null)
		{
			foreach (var entity in currentSnapshotCollection.ToList<object>())
			{
				_relationshipsSnapshot.RemoveFromCollection(navigation, entity);
			}
		}

		var snapshotCollection = (IEnumerable?)value;
		if (snapshotCollection != null)
		{
			foreach (var entity in snapshotCollection)
			{
				_relationshipsSnapshot.AddToCollection(navigation, entity);
			}
		}
	}
	else
	{
		_relationshipsSnapshot.SetValue(navigation, value);
	}
}

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions