Search code examples
c#entity-frameworkxunit.netaspnetboilerplate

Why is my DbContext being disposed? How can I stop it or work around it?


I am getting an ObjectDisposedException on my dbContext object on the last line of this unit test:

public class InvoiceRepository_Tests : AppTestBase
{
    [Fact]
    public async Task Test_InsertAndQuery()
    {
        var invoiceRepository = Resolve<IRepository<InvoiceHistory, long>>();
        var invoice = new InvoiceHistory() { Reference = "1", Payments = new List<Payment> { new Payment() } };
        var ihId = await invoiceRepository.InsertAndGetIdAsync(invoice);
        var readInvoice = await invoiceRepository
            .Query(q => q.Where(ih => ih.Id == ihId))
            .Include(ih => ih.Payments)
            .FirstOrDefaultAsync();
    }
}

If I replace the last line with:

        var readInvoice = invoiceRepository.Get(ihId);

I don't get the error (and do get my parent record), but then I seem to have no option to populate my Payments collection.

I'm not disposing the DbContext anywhere on purpose. In fact, as far as I can tell the only place I've touched it is to add the DbSet's for these two tables and establish the HasMany relationship in OnModelCreating().

I've tried adding [UnitOfWork] to the test, which is the only suggestion I could find elsewhere, but it didn't change the behaviour.


Solution

  • You can Begin the UnitOfWork explicitly:

    [Fact]
    public async Task Test_InsertAndQuery()
    {
        var invoiceRepository = Resolve<IRepository<InvoiceHistory, long>>();
        var unitOfWorkManager = Resolve<IUnitOfWorkManager>();
    
        using (var uow = unitOfWorkManager.Begin())
        {
            var invoice = new InvoiceHistory() { Reference = "1", Payments = new List<Payment> { new Payment() } };
            var ihId = await invoiceRepository.InsertAndGetIdAsync(invoice);
            var readInvoice = await invoiceRepository
                .Query(q => q.Where(ih => ih.Id == ihId))
                .Include(ih => ih.Payments)
                .FirstOrDefaultAsync();
    
            // ...
    
            await uow.CompleteAsync();
        }
    }
    

    [UnitOfWork] attribute is not used on Test methods as the Test class may not be injected.