【问题标题】:Why is my DB context being disposed为什么我的数据库上下文被处置
【发布时间】:2017-05-18 21:22:59
【问题描述】:

与我最近的大多数帖子一样,我首先要说这对我来说是全新的,而且我处于理解的边缘。我正在处理现有应用程序并遇到上述错误。

该应用程序是一个有 3 层的 MVC 应用程序,并且正在通过 Swagger 运行:

Rest

Services

DAL

在服务层DependencyConfig,我在Register方法中做了如下操作,注册了上下文:

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

到目前为止,这一切似乎都运行良好,因为应用程序的某些部分正在从数据库中读取和写入 - 尽管此应用程序中有很多内容,但我并不完全理解。

接下来,在 Rest 层,我有以下内容:

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);
    }
 }

还有来自服务层:

public class AuthorizationManager
    {
        private readonly IApplicationUserService _userService;

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

            //...
        }
    }

最后还有服务层:

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);
        }
}

其中ApplicationUser 是 DAL 层上的模型。

我希望到目前为止这一切都有意义!

问题是当代码到达这一行时:

return _userManager.FindById(id);

它会抛出一个InvalidOperationException: The operation cannot be completed because the DbContext has been disposed.

在我看来,它已经失去了上下文,例如数据库连接。

似乎已经从 register 方法中处理掉了 DbContext - 但我不知道为什么?

如果我手动创建这样的上下文:

Context.Users.Find(id);

我能够检索到所需的条目,但问题再次出现 - 而且我不认为该应用程序打算像这样工作。

所以我的问题是,它为什么要处理我的上下文,我该如何阻止它这样做?

单步执行代码没有帮助,我没有想法。

【问题讨论】:

  • 请同时发布UserManager 代码。
  • ApplicationUserService 构造函数有什么有趣的吗?
  • 您的任何服务是否实现了IDisposable,如果是,它们会处理上下文吗?如果你使用依赖注入,DI 容器应该负责它注入的对象的生命周期。它将负责在何时处理需要处理的内容。
  • 它所在的层无关紧要。它是否在其Dispose 方法中处理您的上下文?如果是这样,请将其删除,然后查看问题是否仍然存在。
  • 也许吧。如果不能看到所有代码,很难说。一般来说,需要非常小心地管理对象的生命周期。任何相互依赖的对象都应该具有相同的生命周期,并且您的 DI 容器应该管理所有这些对象。例如,如果您的 UserManager 与您注入的 UserStore 的生命周期不同,则可能会导致问题,或者如果您的 DI 容器仅管理 UserStore 而不是 UserManager。此外,在 Web 应用程序的上下文中,所有内容都应该是“请求”范围的。其他任何事情都可能导致问题。

标签: c# asp.net-mvc entity-framework


【解决方案1】:

问题与这一行有关:

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

由于 lifestlye.scoped,此时上下文正在被处理掉。

我需要将此添加到container

container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

根据这些说明:http://simpleinjector.readthedocs.io/en/latest/lifetimes.html#perwebrequest

仅在网络请求结束时处理对象

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-02
    • 2010-09-28
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 1970-01-01
    • 2015-08-11
    相关资源
    最近更新 更多