Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dispose of entity objects created by DbContext

We are implementing DAL with EF Core and Postgres Npgsql provider.

Some tables have jsonb columns and we map them to JsonDocument properties in entity objects.

The page JSON Mapping in Npgsql documentation has the following note:

Note also that JsonDocument is disposable, so the entity type is made disposable as well; not dispose the JsonDocument will result in the memory not being returned to the pool, which will increase GC impact across various parts of the framework.

According to the doc, we have made the entities disposable:

public class SomeEntity : IDisposable
{
    public int Id { get; set; }

    public JsonDocument JsonData { get; set; }

    public void Dispose()
    {
        JsonData?.Dispose();
    }
}

The problem is that Dispose method for entity objects is never called while DbContext is disposed correctly. The only way we see is to manually enumerate DbSet when DbContext is disposed and invoke Dispose method for each entity:

public class SomeDbContext : DbContext
{
    public DbSet<SomeEntity> SomeEntities { get; set; }

    private bool DisposedEntities { get; set; }

    public override void Dispose()
    {
        DisposeEntities();

        base.Dispose();
    }

    public override ValueTask DisposeAsync()
    {
        DisposeEntities();

        return base.DisposeAsync();
    }

    private void DisposeEntities()
    {
        if (DisposedEntities)
        {
            return;
        }

        DisposeEntities(SomeEntities);

        DisposedEntities = true;
    }

    private static void DisposeEntities<TEntity>(IEnumerable<TEntity> dbSet)
        where TEntity : IDisposable
    {
        foreach (var entity in dbSet)
        {
            entity.Dispose();
        }
    }
}

Is there a way to force EF Core to dispose entities when DbContext is disposed?

Is above approach with manual entities dispose OK or it has some flaws?

like image 214
CodeFuller Avatar asked Feb 28 '26 06:02

CodeFuller


2 Answers

While your approach will work, the intent isn't generally for the DbContext to "own" the entity instances it hands out (and therefore to dispose them when it itself is disposed). You use a DbContext to get out instances, but at that point they are yours - it's perfect reasonable for them to outlive the context through which they were created.

In other words, it really is up to your application code to call Dispose when done with an entity instance.

Note also that if Dispose isn't called, there's no leak or anything, and so no catastrophic problem; all it means is that GC pressure will be higher, possibly causing some performance degradation.

like image 63
Shay Rojansky Avatar answered Mar 01 '26 21:03

Shay Rojansky


Not OK. Your implementation loads whole table during dispose, because when enumerating DbSet - it loads data from database.

Consider to change function signature and dispose entities from Local collection:

private static void DisposeEntities<T>(DbSet<T> dbSet) 
    where T : class, IDisposable
{
    foreach (var entity in dbSet.Local)
    {
        entity.Dispose();
    }
}
like image 44
Svyatoslav Danyliv Avatar answered Mar 01 '26 20:03

Svyatoslav Danyliv



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!