Solving "The Objectcontext Instance Has Been Disposed and Can No Longer Be Used For Operations That Require a Connection" Invalidoperationexception

Solving The ObjectContext instance has been disposed and can no longer be used for operations that require a connection InvalidOperationException

By default Entity Framework uses lazy-loading for navigation properties. That's why these properties should be marked as virtual - EF creates proxy class for your entity and overrides navigation properties to allow lazy-loading. E.g. if you have this entity:

public class MemberLoan
{
public string LoandProviderCode { get; set; }
public virtual Membership Membership { get; set; }
}

Entity Framework will return proxy inherited from this entity and provide DbContext instance to this proxy in order to allow lazy loading of membership later:

public class MemberLoanProxy : MemberLoan
{
private CosisEntities db;
private int membershipId;
private Membership membership;

public override Membership Membership
{
get
{
if (membership == null)
membership = db.Memberships.Find(membershipId);
return membership;
}
set { membership = value; }
}
}

So, entity has instance of DbContext which was used for loading entity. That's your problem. You have using block around CosisEntities usage. Which disposes context before entities are returned. When some code later tries to use lazy-loaded navigation property, it fails, because context is disposed at that moment.

To fix this behavior you can use eager loading of navigation properties which you will need later:

IQueryable<MemberLoan> query = db.MemberLoans.Include(m => m.Membership);

That will pre-load all memberships and lazy-loading will not be used. For details see Loading Related Entities article on MSDN.

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. in Reference table

You are trying to access an association property Country after the data context has been disposed. Entity Framework, by default, loads association properties lazily. In other words, it makes another trip to the database when you try to access the association property for the first time. To make this trip to the database, Entity Framework must use a data context. In your case, it would be trying to use the data context created by jQGridDemoEntities db = new jQGridDemoEntities() which has unfortunately been disposed at this point in your code. The data context has been disposed because you've exited the using block.

You have three options to get around this problem:

  • Access the association property when the data context is still alive. More concretely, move your code where you access the association property into your using block

  • Eagerly load the association property as explained in the first link I specified

    customers = db.Customers.Include(c => c.Country).ToList()

  • Explicitly select what you want to return from the database while the data context is still alive. And use that information to construct the json object your return.

    customers = db.Customers.Select(c => new
    {
    c.Id,
    c.FirstName,
    c.LastName,
    c.Address,
    c.Email,
    c.Phone,
    CountryName = c.Country.Name,
    c.Note
    };

How can I fix The ObjectContext instance has been disposed

This issue often stems from the serializer which will be touching all properties on the entity being serialized to send to the view. If the DbContext the entity was associated with gets disposed, the serializer will hit this when attempting to issue queries to load the related details.

The quick fix, if noteManager.ListQueryable() returns IQueryable<Note> would be:

return View(noteManager.ListQueryable()
.Include(x => x.Owner)
.Include(x => x.Comments)
.Include(x => x.Category)
.Include(x => x.Likes)
.Where(x => x.IsDraft == false && x.IsApproved == true)
.OrderByDescending(x => x.ModifiedOn)
.Take(10).ToList());

This eager loads the related entities along with the notes. The difference between eager loading and lazy loading is that with an eager load, EF will generate SQL to Join all of the associated tables then retrieve the related rows for the up to 10 selected rows. With lazy loading you might have 10 note rows, ID's 1-10 for instance, but as each property is touched, EF will generate a queries like:

SELECT * FROM Owners WHERE OwnerID = 22 -- Owner ID on note 1

SELECT * FROM Comments WHERE NoteId = 1

SELECT * FROM Categories WHERE CategoryId = 4 Category ID on note 1

SELECT * FROM Likes WHERE NoteId = 1

Then repeat that 9 more times, once for each note row returned. That is a lot of queries that EF and the DB need to negotiate while the entity's proxy is holding a weak reference to the DbContext. If the request disposes of the DbContext before the serializer finishes with the entity, you're handed a steaming Exception.

However, Even with eager loading this can be a rabbit hole if any of those related entities have child entities themselves. There is also the performance/resource implications of loading all of that related data that your view probably won't need.

The better long term solution is to define serializable ViewModels to represent the data structure your view actually needs to display, then leverage Select or Automapper's ProjectTo to fill that view model with data from the entity structure. This negates the need to eager load data, just Select from the structure and EF will work out the SQL. It also removes the risk of lazy load hits in the serializer provided you Select fields from the entities and not the entities themselves. This also can greatly reduce the amount of memory needed on the server & client to store the data when requested, and the data transmission size.

Passing view models to the view means passing the same, or different view models back to the server rather than trying to pass back entities, attach, and save... Which looks like more work and a time saving compared to loading the data again and copying the values across. However, this is much safer as you don't risk stale, incomplete, or potentially tampered data overwriting your real data. You should always reload the entities when performing an update anyways to validate and check that the row(s) have not been modified since they were sent to the client. Trust nothing that comes from a web client. Copying fields to a freshly loaded entity also means more efficient UPDATE statements as Attaching + EntityState.Modified or using DbContext.Update() result in update statements that update all fields, vs with copy across, only the values that are changed will be added to the UPDATE statement.

error:The ObjectContext instance has been disposed and can no longer be used for operations that require a connection

Company should be lazy-loaded in your case. But your entity now in detached state (context which loaded KBrand entity now disposed. So, when you are trying to access Company property, Entity Framework tries to use disposed context to make query to server. That gives you exception.

You need to attach your KBrand entity to current context in order to enable lazy-loading

RSPDbContext c = new RSPDbContext();
KBrand co = item.Tag as KBrand;
c.KBrands.Attach(co);
// use co.Company

OR you need to use eager loading, to have Company already loaded. Something like this when you getting items:

RSPDbContext db = new RSPDbContext();
var brands = db.KBrands.Include(b => b.Company).ToList();
// assign brands to listbox

I'm getting The ObjectContext instance has been disposed, even though nothing has been disposed

You're passing a lazily-loaded EntityFramework ICollection to the Json(..) method. At the time that the response is serialized, the EntityFramework context will have been disposed.

Add .ToList() to the end of your ICollection/IQueryable/IEnumerable, before you pass it.

return Json(meta.ToList(), JsonRequestBehavior.AllowGet);

ASP.NET MVC5: The ObjectContext instance has been disposed

Solution found.
In this case me helped 2 methods:

1) context.Configuration.LazyLoadingEnabled = false;
2) or using .Include()

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.'

You're getting exception because of this: get_CarGame().

Code inside original post doesn't match your actual code.

Somewhere inside actual MainPageController.GetUserInfo you're trying to read ApplicationUser.CarGame. And yes, this is lazy loading issue.

GetLoggedInUserInDB returns instance of proxy class, derived from ApplicationUser, and disposes original context. When GetUserInfo tries to get CarGame property value, proxy attempts to read it from database, using disposed context. As a result, exception is being thrown.

If you really need CarGame inside UserInfoModel:

  • either turn off lazy loading as shown above, and use eager loading;
  • use projection (that is, Select) to retrieve user info as UserInfoModel in place. In this case there is no need in GetLoggedInUserInDB method at all.

Anyway, attaching LoggedUser to another context is not a way to go.

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. - List

You should include them in your original query. You can do this using Include:

List<Item> items;
using (var context = new YourContext())
{
items = context.Items.Include(x => x.Messages).ToList();
}


Related Topics



Leave a reply



Submit