Question

Okay so I have no clue what is going on and why I keep getting the error that my db context has been disposed. Let me show you what I have then step you through it.

Controller :

[HttpPost]
public ActionResult UserProfile(UserProfileViewModel model)
{
    bool success = false;
    var user = UserRepository.GetUserById((int)Session["UserId"]);

    success = user.FriendId == null
        ? FriendRepository.CreateUserProfile((int) Session["UserId"], model)
        : FriendRepository.UpdateUserProfile((int) Session["UserId"], model);

    if (!success) return View("UserProfile");

    UpdateSession((int) Session["UserId"]);
    return RedirectToAction("AddSteamQuestion", "Steam");
}

private void UpdateSession(int id)
{
    var user = UserRepository.GetUserById((int)Session["UserId"]);
    Session["UserFirstName"] = user.Friend.Alias;

}

So first it grabs the User which it successfully does. Then it inserts or updates the user profile in my repo. Which also appears to be successful. Then finally it needs to update the user name in the session (just in case they changed it). So it jumps down to the Update session method and then I get the thrown error? It's not like GetUserId is broken I use it tons in my application. In fact it successfully pulls that data on the first var user in the UserProfile method.

The error says DbContext has been disposed.

Here is my crazy huge Repo for GetUserById (it breaks right on the var user = ):

public UserModel GetUserById(int sessionId)
        {
            try
            {
                using (db)
                {
                    var user = (from u in db.Users
                                join f in db.Friends on u.FriendId equals f.Id
                                where u.Id == sessionId
                                select new UserModel()
                                {
                                    CreatedOn = u.CreatedOn,
                                    EmailAddress = u.EmailAddress,
                                    FriendId = u.FriendId,
                                    Id = u.Id,
                                    RoleId = u.RoleId,
                                    Friend = new FriendModel
                                    {
                                        Alias = f.Alias,
                                        CarrierId = f.CarrierId,
                                        CreatedOn = f.CreatedOn,
                                        FirstName = f.FirstName,
                                        Id = f.Id,
                                        LastName = f.LastName,
                                        Locked = f.Locked,
                                        PhoneNumber = f.PhoneNumber,
                                        SteamId = f.SteamId
                                    }

                                }).SingleOrDefault();
                    return user;
                }
            }
            catch (SqlException e)
            {
                throw new InvalidOperationException("Cannot Get User By Id", e);
            }
        }
Was it helpful?

Solution

Your db which I assume is a private field for your dbContext has been disposed by the garbage collector so when you try to access db.users you will get the error you are seeing. I would write it like this:

using (var db = new YourDataContext()) {
    ...// do work here
}

Put this in place of your:

using (db)

This will ensure correct creation and disposing of your DbContext.

OTHER TIPS

When you put an object in a using() statement, it "disposes" the object when the block is exited. This is so that the object can clean up things like database connections. Once the object has been disposed, it can no longer be used and you'll need to create a new one.

It looks like db is a variable that you are creating once and holding onto - but after the using statement disposes of it, it cannot be used again. Modify your code so that you create a new data context each time you access the database, like this:

using (DatabaseContext db = new DatabaseContext())
{
    ... // Do things here
}

Whenever you use a using statement, declare the object inside the statement. This is especially true for database transactions, since you can run into major issues with concurrency and caching later on if you hang onto the same context. Keep your contexts localized and dispose of them as soon as you are done with a transaction.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top