简体   繁体   中英

Why is my DB context being disposed

As with most of my recent posts, I will start by saying this is all new to me, and I am on the edge of my understanding. I am working on an existing application and have come across the above error.

The application is an MVC application that has 3 layers, and is being run through Swagger:

Rest

Services

DAL

In the service layer DependencyConfig , I do the following in the Register Method, the context is registered:

container.RegisterWebApiRequest<DbContext>(() => new LocalContext("name=DefaultConnection"));

So far this all seems to be working fine, as parts of the application are reading and writing from the database - although there is a lot in this application and I do not understand all of it.

Next, on the Rest layer, I have the following:

public class AccountController : ApiController
{
    private readonly WindowsAuthenticationProvider _windowsAuthentication;
    private readonly AuthorizationManager _authorizationManager;
    private readonly IApplicationUserService _userService;
    private readonly IProfileService _profileService;
    private readonly IAccountLogsService _accountLogsService;

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="authorizationManager">Authorization Manager</param>
    /// <param name="windowsAuthentication">Enables windows reauthentication without a session</param>
    public AccountController(AuthorizationManager authorizationManager, WindowsAuthenticationProvider windowsAuthentication,
        IApplicationUserService userService, IProfileService profileService, IAccountLogsService accountLogsService)
    {
        _windowsAuthentication = windowsAuthentication;
        _authorizationManager = authorizationManager;
        _userService = userService;
        _profileService = profileService;
        _accountLogsService = accountLogsService;
    }

    /// <summary>
    /// Get logged in user details
    /// </summary>
    /// <remarks>Retrieves details of the currently logged in user</remarks>
    [Authorize]
    [HttpGet]
    [Route("")]
    [ResponseType(typeof(AccountDetailsModel))]
    public IHttpActionResult Details()
    {
        var userId = User.Identity.GetUserId<int>();

        var model = //...

        if (model.HasAccount)
        {
            var user = _authorizationManager.FindUser(User.Identity);
        }

        return Ok(model);
    }
 }

and also from the services layer:

public class AuthorizationManager
    {
        private readonly IApplicationUserService _userService;

        public ApplicationUser FindUser(IIdentity identity)
        {
            var userId = identity.GetUserId<int>();
            if (userId != 0)
            {
                return _userService.FindById(userId);
            }

            //...
        }
    }

and finally also on the services layer:

public class ApplicationUserService : UnitOfWork<LocalContext>, IApplicationUserService
    {
        private readonly UserManager<ApplicationUser, int> _userManager;
        private readonly RoleManager<ApplicationRole, int> _roleManager;

        /// <summary>
        /// Finds a user by id
        /// </summary>
        /// <param name="id">User id</param>
        /// <returns>ApplicationUser</returns>
        public ApplicationUser FindById(int id)
        {
            return _userManager.FindById(id);
        }
}

Where ApplicationUser is a model on the DAL layer.

I hope this all makes sense so far!

The problem is that when the code gets to this line:

return _userManager.FindById(id);

it throws an InvalidOperationException: The operation cannot be completed because the DbContext has been disposed.

Which seems to me to be saying it has lost the context eg database connection.

It seems to have disposed of the DbContext from the register method - but I have no idea why?

If I manually create a context like this:

Context.Users.Find(id);

I am able to retrieve the required entry, but the problem re occurs further down the line - and I do not think the application was intended to work like this.

So my question is, why is it disposing of my context and how can I stop it doing so?

Stepping through the code does not help and I am out of ideas.

The problem was to do with this line:

container.Register<IUserStore<ApplicationUser, int>, UserStore <ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>>(Lifestyle.Scoped);

Because of lifestlye.scoped, the context was being disposed of at this point.

I needed to add this to the container :

container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

from these instructions: http://simpleinjector.readthedocs.io/en/latest/lifetimes.html#perwebrequest

Which only disposed of the object at the end of the web request

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