Skip to content

Commit

Permalink
Cleat StateManager event handlers when context returned to pool
Browse files Browse the repository at this point in the history
Fixes #13087
  • Loading branch information
ajcvickers committed Oct 2, 2018
1 parent 345af5b commit badbad7
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 26 deletions.
3 changes: 3 additions & 0 deletions src/EFCore/ChangeTracking/Internal/StateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,9 @@ public virtual void ResetState()
_queryIsTracked = false;
_trackingQueryMode = TrackingQueryMode.Simple;
_singleQueryModeEntityType = null;

Tracked = null;
StateChanged = null;
}

/// <summary>
Expand Down
139 changes: 113 additions & 26 deletions test/EFCore.Tests/ChangeTracking/ChangeTrackerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
Expand Down Expand Up @@ -456,10 +457,12 @@ public void State_change_events_fire_from_query()
var tracked = new List<EntityTrackedEventArgs>();
var changed = new List<EntityStateChangedEventArgs>();

Seed();
Seed(usePool: true);

using (var context = new LikeAZooContext())
using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

RegisterEvents(context, tracked, changed);

Assert.Equal(2, context.Cats.OrderBy(e => e.Id).ToList().Count);
Expand All @@ -470,6 +473,16 @@ public void State_change_events_fire_from_query()
AssertTrackedEvent(context, 1, EntityState.Unchanged, tracked[0], fromQuery: true);
AssertTrackedEvent(context, 2, EntityState.Unchanged, tracked[1], fromQuery: true);
}

using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

Assert.Equal(2, context.Cats.OrderBy(e => e.Id).ToList().Count);

Assert.Equal(2, tracked.Count);
Assert.Equal(0, changed.Count);
}
}

[Fact]
Expand All @@ -478,8 +491,10 @@ public void State_change_events_fire_from_Attach()
var tracked = new List<EntityTrackedEventArgs>();
var changed = new List<EntityStateChangedEventArgs>();

using (var context = new LikeAZooContext())
using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

RegisterEvents(context, tracked, changed);

context.Attach(new Cat(1));
Expand All @@ -504,8 +519,10 @@ public void State_change_events_fire_from_Add()
var tracked = new List<EntityTrackedEventArgs>();
var changed = new List<EntityStateChangedEventArgs>();

using (var context = new LikeAZooContext())
using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

RegisterEvents(context, tracked, changed);

context.Add(new Cat(1));
Expand All @@ -530,8 +547,10 @@ public void State_change_events_fire_from_Update()
var tracked = new List<EntityTrackedEventArgs>();
var changed = new List<EntityStateChangedEventArgs>();

using (var context = new LikeAZooContext())
using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

RegisterEvents(context, tracked, changed);

context.Update(new Cat(1));
Expand All @@ -556,8 +575,10 @@ public void State_change_events_fire_for_tracked_state_changes()
var tracked = new List<EntityTrackedEventArgs>();
var changed = new List<EntityStateChangedEventArgs>();

using (var context = new LikeAZooContext())
using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

RegisterEvents(context, tracked, changed);

context.AddRange(new Cat(1), new Cat(2));
Expand Down Expand Up @@ -595,6 +616,25 @@ public void State_change_events_fire_for_tracked_state_changes()
AssertChangedEvent(context, null, EntityState.Added, EntityState.Detached, changed[4]);
AssertChangedEvent(context, null, EntityState.Deleted, EntityState.Detached, changed[5]);
}

using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

context.AddRange(new Cat(1), new Cat(2));

context.Entry(context.Cats.Find(1)).State = EntityState.Unchanged;
context.Entry(context.Cats.Find(2)).State = EntityState.Modified;

context.Entry(context.Cats.Find(1)).State = EntityState.Added;
context.Entry(context.Cats.Find(2)).State = EntityState.Deleted;

context.Remove(context.Cats.Find(1));
context.Entry(context.Cats.Find(2)).State = EntityState.Detached;

Assert.Equal(2, tracked.Count);
Assert.Equal(6, changed.Count);
}
}

[Fact]
Expand All @@ -603,10 +643,12 @@ public void State_change_events_fire_when_saving_changes()
var tracked = new List<EntityTrackedEventArgs>();
var changed = new List<EntityStateChangedEventArgs>();

Seed();
Seed(usePool: true);

using (var context = new LikeAZooContext())
using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

RegisterEvents(context, tracked, changed);

var cat1 = context.Cats.Find(1);
Expand Down Expand Up @@ -634,6 +676,8 @@ public void State_change_events_fire_when_saving_changes()

AssertChangedEvent(context, 1, EntityState.Modified, EntityState.Unchanged, changed[1]);
AssertChangedEvent(context, 3, EntityState.Added, EntityState.Unchanged, changed[2]);

context.Database.EnsureDeleted();
}
}

Expand All @@ -643,8 +687,10 @@ public void State_change_events_fire_when_property_modified_flags_cause_state_ch
var tracked = new List<EntityTrackedEventArgs>();
var changed = new List<EntityStateChangedEventArgs>();

using (var context = new LikeAZooContext())
using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

RegisterEvents(context, tracked, changed);

var cat = context.Attach(
Expand Down Expand Up @@ -682,14 +728,18 @@ public void State_change_events_are_limited_to_the_current_context()
var tracked2 = new List<EntityTrackedEventArgs>();
var changed2 = new List<EntityStateChangedEventArgs>();

Seed();
Seed(usePool: true);

using (var context = new LikeAZooContext())
using (var scope = _poolProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<LikeAZooContextPooled>();

RegisterEvents(context, tracked1, changed1);

using (var context2 = new LikeAZooContext())
using (var scope2 = _poolProvider.CreateScope())
{
var context2 = scope2.ServiceProvider.GetService<LikeAZooContextPooled>();

RegisterEvents(context2, tracked2, changed2);

Assert.Equal(2, context2.Cats.OrderBy(e => e.Id).ToList().Count);
Expand Down Expand Up @@ -718,6 +768,8 @@ public void State_change_events_are_limited_to_the_current_context()

Assert.Equal(2, tracked2.Count);
Assert.Equal(1, changed2.Count);

context.Database.EnsureDeleted();
}
}

Expand Down Expand Up @@ -797,8 +849,37 @@ private class Hat
private static readonly ListLoggerFactory _loggerFactory
= new ListLoggerFactory();

private static readonly IServiceProvider _poolProvider
= new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.AddDbContextPool<LikeAZooContextPooled>(
p => p.UseInMemoryDatabase(nameof(LikeAZooContextPooled))
.UseLoggerFactory(_loggerFactory))
.BuildServiceProvider();

private class LikeAZooContextPooled : LikeAZooContext
{
public LikeAZooContextPooled(DbContextOptions<LikeAZooContextPooled> options)
: base(options)
{
}

protected internal override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
}
}

private class LikeAZooContext : DbContext
{
public LikeAZooContext()
{
}

protected LikeAZooContext(DbContextOptions options)
: base(options)
{
}

public DbSet<Cat> Cats { get; set; }

protected internal override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
Expand All @@ -816,31 +897,37 @@ protected internal override void OnConfiguring(DbContextOptionsBuilder optionsBu
.UseInMemoryDatabase(nameof(LikeAZooContextSensitive));
}

private void Seed(bool sensitive = false)
private void Seed(bool sensitive = false, bool usePool = false)
{
using (var context = sensitive ? new LikeAZooContextSensitive() : new LikeAZooContext())
void Seed(LikeAZooContext context)
{
context.Database.EnsureDeleted();

var cat1 = new Cat(1)
{
Name = "Smokey"
};
var cat2 = new Cat(2)
{
Name = "Sid"
};
var cat1 = new Cat(1) { Name = "Smokey" };
var cat2 = new Cat(2) { Name = "Sid" };

cat1.Hats.Add(
new Hat(77)
{
Color = "Pine Green"
});
new Hat(77) { Color = "Pine Green" });

context.AddRange(cat1, cat2);

context.SaveChanges();
}

if (usePool)
{
using (var scope = _poolProvider.CreateScope())
{
Seed(scope.ServiceProvider.GetService<LikeAZooContextPooled>());
}
}
else
{
using (var context = sensitive ? new LikeAZooContextSensitive() : new LikeAZooContext())
{
Seed(context);
}
}
}

[Theory]
Expand Down

0 comments on commit badbad7

Please sign in to comment.