【发布时间】: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