简体   繁体   中英

The operation cannot be completed because the DbContext has been disposed in Web API

My api call is throwing exception "The operation cannot be completed because the DbContext has been disposed". please guide how to resolve it..

Function which is defined in seprate class named as Common Class

public IQueryable productquery()
    {
        try
        {
            using (ERPEntities db = new ERPEntities())
            {
                db.Configuration.ProxyCreationEnabled = false;
                var query = db.Products.OrderBy(x => x.ID).AsQueryable();
                var list = query.Skip(10).Take(50).AsQueryable();
                return list;
            }
        }
        catch (Exception ex)
        {
            throw;
        };
    }

Function Call from common function to api Controller

[HttpPost]
    public IHttpActionResult GetProducts()
    {
        try
        {
            var result = _commonFunctions.productquery();
            var resultf = result.Include(x => x.Catagory).ToList();
            return Ok(resultf);
        }
        catch (Exception ex)
        {
            return BadRequest(ex.Message);
        }
    } 

You are trying to include an entity after your DbContext has been disposed.

var resultf = result.Include(x => x.Catagory).ToList();

But you are calling DbContext with using inside productquery() method. If you want to continue to do so, you should finish all db actions inside the using part.

var query = db.Products.Include(x => x.Catagory).OrderBy(x => x.ID).AsQueryable();

The problem is that you create your context:

ERPEntities db = new ERPEntities()

but wrapping it up in a using statement, it would dispose it after the return statement:

return list;

( Undoubtedly you need the disposal of the DB context class , but you have to use the DB context class prior to its disposal. Afterwards, apparently you can't use it.)

For that reason in GetProducts fails, when you materialize the query.

One solution it would be to call ToList before AsQueryable .

var list = query.Skip(10).Take(50).ToList().AsQueryable(); 

Essentially this would would materialize your query, the data would be fetched from the database, when you call ToList and later on you wouldn't need the context. However, you would have a new problem, Include(x => x.Catagory) . This should placed, where you build the query:

var query = db.Products
              .Include(x => x.Catagory)
              .OrderBy(x => x.ID)
              .AsQueryable();

Doing so, I would say that you don't need any more the call to AsQueryable you can removed it from both the signature of your method and the the places you call it.

The most correct answer is to use dependency injection to pass around one instance of your DBContext per http request.

However, the problem is actually just that you are disposing you DBContext before you're done with it. You can move your DBContext to a class-level variable and instantiate it in the CommonFunctions class' constructor. Then you can destroy it on Dispose. This will make it possible for you to do what you want. You will also have to create a function called SaveChanges() which calls.SaveChanges() on the context when you're done doing whatever it is you're doing that needs saving. This is a very quick explanation of something called the Unit of Work pattern.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM