Cannot access a disposed object. A common cause of this error is disposing a context

.net .net-core entity-framework entity-framework-core

Question

I have written a simple application and when I navigate to my edit page the below error pops up.

Microsoft.EntityFrameworkCore.Query[10100]

An exception occurred while iterating over the results of a query for context type 'app.Models.ApplicationDbContext'.

System.ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.

It seems EF is proving a useful information which I can not understand. The tricky part of this error is that it happens randomly when I navigate to the edit page. Sometime it works, Sometimes it fails to load some properties on Edit.cshtml but still works and sometimes the application crashes with provided error just in my console. Another strange happen is that it dose not generate any 500 or 5xx error. It just simply crashes and stop the application.

Here is my Edit.cshtml content:

@page
@model EditModel
@{
    ViewData["Title"] = "Edit Book";
}

<h2>Edit Book</h2>

<div class="row justify-content-center">
    <div class="col-md-6">
        <form method="post" class="form-border">
            <div asp-validation-summary="All" class="validation-container alert alert-danger"></div>
            <div class="form-group">
                <label asp-for="Book.Name"></label>
                <input asp-for="Book.Name" class="form-control" />
                <span class="form-text text-danger" asp-validation-for="Book.Name"></span>
            </div>
            <div class="form-group">
                <label asp-for="Book.Description"></label>
                <input asp-for="Book.Description" class="form-control" />
            </div>
            <div class="form-group">
                <label asp-for="Book.Author"></label>
                <input asp-for="Book.Author" class="form-control" />
            </div>
            <input asp-for="Book.Id" type="hidden">
            <button type="submit" class="btn btn-primary">Update</button>
            <a asp-page="Index" class="btn btn-success">Back To List</a>
        </form>
    </div>
</div>

Here is My Edit.cshtm.cs OnGet method:

public async void OnGet(int id)
{
    Book = await _db.Books.SingleOrDefaultAsync(x => x.Id == id);

    if(Book == null)
    {
        RedirectToPage("Index");
    }
}

I am using .Net Core 2.2.104

Also when I run command dotnet ef --version it generates Entity Framework Core .NET Command-line Tools 2.2.2-servicing-10034

1
9
4/6/2019 6:23:32 AM

Accepted Answer

This is because of your method return type async void. In general, when you are using async void in your code it’s bad news, because:

  • You can’t wait for its completion
  • Any unhandled exceptions will terminate your process (ouch!)

So return async Task instead of async void from your method as follows:

public async Task OnGet(int id)
{
    Book = await _db.Books.SingleOrDefaultAsync(x => x.Id == id);

    if(Book == null)
    {
       RedirectToPage("Index");
    }
}

For more details:

21
4/6/2019 2:50:14 AM

Popular Answer

What I am about to post is NOT the answer to this particular question. But it is related so just to save somebody headache I am posting it. I was encountering this same error

System.ObjectDisposedException: Cannot access a disposed object. etc

The following was the code with the bug (can you see it):

[HttpGet("processs/oxxo-spei/ticket-email/{paymentIdx}")]
        public StatusCodeResult ProcessOxxoSpeiTicketEmailAsync(string paymentIdx)
        {
            var paymentId = paymentIdx.DecodeRef();
            
            var response = _orderEngine.ProcessOxxoSpeiTicketEmailAsync(paymentId);

            return StatusCode(200);
        }

The following change fixed it:

[HttpGet("processs/oxxo-spei/ticket-email/{paymentIdx}")]
        public async Task<StatusCodeResult> ProcessOxxoSpeiTicketEmailAsync(string paymentIdx)
        {
            var paymentId = paymentIdx.DecodeRef();
            
            var response = await _orderEngine.ProcessOxxoSpeiTicketEmailAsync(paymentId);
                       // ^^^^I HAD FORGOTTEN TO PUT AWAIT
            return StatusCode(200);
        }

Yes that's right I had forgotten to put "await" before a function that used an EF Core dbcontext. Adding 'await' fixed it. So easy to miss it, especially if you're tired and under deadline.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow