Skip to content

Commit

Permalink
Don't attempt to remove a detached entry from the local view (#35253)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers authored Dec 17, 2024
1 parent c6aba69 commit b8ddc5b
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
3 changes: 1 addition & 2 deletions src/EFCore/ChangeTracking/LocalView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,7 @@ public virtual void CopyTo(TEntity[] array, int arrayIndex)
public virtual bool Remove(TEntity item)
{
var entry = _context.GetDependencies().StateManager.TryGetEntry(item);
if (entry != null
&& entry.EntityState != EntityState.Deleted)
if (entry is { EntityState: not EntityState.Deleted and not EntityState.Detached })
{
try
{
Expand Down
72 changes: 72 additions & 0 deletions test/EFCore.Specification.Tests/DataBindingTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,78 @@ public virtual void Entities_with_state_changed_to_deleted_are_removed_from_loca
Assert.Equal(TotalCount - UnchangedCount, local.Count);
}

[ConditionalTheory]
[InlineData(false)]
[InlineData(true)] // Issue #35243
public virtual void Remove_detached_entity_from_LocalView(bool toObservableCollection)
{
using var context = CreateF1Context();
var localView = context.Drivers.Local;
var local = toObservableCollection
? (ICollection<Driver>)localView.ToObservableCollection()
: localView;

Assert.Equal(0, local.Count);

var driver1 = new Driver
{
Id = -1,
Name = "Larry David",
TeamId = Team.Ferrari,
CarNumber = 13
};

var driver2 = new Driver
{
Id = -2,
Name = "Jerry Seinfeld",
TeamId = Team.Mercedes,
CarNumber = 14
};

var driver3 = new Driver
{
Id = -3,
Name = "George Costanza",
TeamId = Team.McLaren,
CarNumber = 15
};

local.Add(driver1);
local.Add(driver2);

Assert.Equal(2, local.Count);
Assert.Equal(2, local.ToList().Count);

Assert.True(local.Contains(driver1));
Assert.True(localView.Contains(driver1));
Assert.True(local.Contains(driver2));
Assert.True(localView.Contains(driver2));
Assert.False(local.Contains(driver3));
Assert.False(localView.Contains(driver3));

context.Entry(driver3);

Assert.True(local.Contains(driver1));
Assert.True(localView.Contains(driver1));
Assert.True(local.Contains(driver2));
Assert.True(localView.Contains(driver2));
Assert.False(local.Contains(driver3));
Assert.False(localView.Contains(driver3));

local.Remove(driver3);

Assert.Equal(2, local.Count);
Assert.Equal(2, local.ToList().Count);

Assert.True(local.Contains(driver1));
Assert.True(localView.Contains(driver1));
Assert.True(local.Contains(driver2));
Assert.True(localView.Contains(driver2));
Assert.False(local.Contains(driver3));
Assert.False(localView.Contains(driver3));
}

[ConditionalTheory]
[InlineData(false)]
[InlineData(true)]
Expand Down

0 comments on commit b8ddc5b

Please sign in to comment.