Special thanks to Andrew Williamson for his splendid edit:
So this:
Avoid using context pooling in apps that maintain state. For example, private fields in the context that shouldn't be shared across requests. EF Core only resets the state that it is aware of before adding a context instance to the pool.
Basically states, that if you use private fields in your DbContext
, like _myPrivateField
, or a private property for that matter, and you use this to do some calculations - using context pooling might result in undesired behavior because you don't know what the initial value will be.
As an example, let's say you have a requirement to log the total number of rows affected during your request. The easiest way to do this would be to override the DbContext to track this:
public class FooContext : DbContext
{
public DbSet<Foo> Foos { get; set; }
public int Updates { get; private set; } = 0;
public override int SaveChanges()
{
Updates += base.SaveChanges();
}
}
Now if we turn on context pooling:
- Request 1 creates a new FooController, which gets a new DbContext
- Request 1 updates a Foo and saves changes, which increments the
Updates
value by 1
- Request 1 logs the message 1 rows affected
- Request 2 creates a new FooController, which reuses the same DbContext
- Request 2 updates a Foo and saves changes, which increments the
Updates
value by 1
- Request 2 logs the message 2 rows affected, which is not right
Entity Framework resets the things that it knows about before giving out a pooled DbContext, but since Updates
is a custom variable, it doesn't know to reset it.
This one is easier:
Context pooling is intended for scenarios where the context configuration, which includes services resolved, is fixed between requests. For cases where Scoped services are required, or configuration needs to be changed, don't use pooling.
Simply states that if you need different configuration options for each DbContext
- pooling is not able to help due to the re-use of the DbContext (and hence, the configuration). An example of this might be a multi-tenant environment where each tenant has their own database:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(CurrentUser.Tenant.ConnectionString);
}
If context pooling is turned on, the connection string will be cached between requests, so a user might start seeing data from a tenant they don't belong to instead of their own data.
About connection pooling
specific, the doc's state that:
Note that DbContext pooling is orthogonal to database connection pooling, which is managed at a lower level in the database driver.
In this sentence "orthogonal" is just a difficult way of saying DbContext pooling
and connection pooling
are independent of each other because connection pooling
is handled by a different mechanism.
Here is a nice article which explains why pooling is helpful:
https://neelbhatt.com/2018/02/27/use-dbcontextpooling-to-improve-the-performance-net-core-2-1-feature/