ASP.NET Identity 的 UserManager 缓存用户?

Fra*_*une 5 c# asp.net-mvc entity-framework unity-container asp.net-identity

我们将 ASP.NET Identity 2.2 与 ASP.NET MVC 5.2、Entity Framework 6.2 和 Unity 5.7 一起使用。

我们有一个ConnectUserManager派生自 ASP.NET Identity 的UserManager. 每次都会UserStore传递一个新构造的UserManager

ConnectUserManager(以及UserManager)的生命周期是每个请求:

Container.RegisterType<ConnectUserManager>(
    new PerRequestLifetimeManager(),
    new InjectionConstructor(
        Container.Resolve<ConnectDbContext>(),
        Container.Resolve<ITemplateManager>(),
        Settings.MaxFailedAccessAttemptsBeforeLockout,
        Settings.AccountLockoutTimeSpan));
Run Code Online (Sandbox Code Playgroud)

当我们需要显示给定用户的详细信息时,控制器操作会检索用户,如下所示:

public async Task<ActionResult> Details(int id)
{
    var user = await UserManager.FindByIdAsync(id);
    ...
}
Run Code Online (Sandbox Code Playgroud)

UserManager注入的属性在哪里:

[Dependency]
public ConnectUserManager UserManager { get; set; }
Run Code Online (Sandbox Code Playgroud)

问题user似乎来自缓存:数据库中的修改似乎对我们的应用程序显示的内容没有任何影响。

这段代码已经投入生产一年了,我们从来没有遇到过任何问题:当我们的代码修改用户时,缓存似乎正确地失效了。

我们现在才注意到这个问题,因为当 Identity 锁定用户时,它会更新用户的LockoutEndDateUtc属性,但似乎没有使缓存失效,并且我们LockoutEndDateUtc在显示中得到了一个陈旧的值。

我们做错了什么?

编辑

@DotNetMatt 在评论中链接了以下问题:
Entity Framework caching in aspnet Identity

除非我遗漏了什么,否则接受的解决方案(无论如何在撰写本文时)似乎与原始海报和我的问题完全无关。

然而,原发帖者似乎自己找到了 (a?) 解决方案:“我所做的是实现了我自己的用户存储并手动访问了 EF 并使用了 .AsNoTracking() 来避免缓存。”

有什么方法可以做到这一点而不必重新实现(或子类化)用户存储?

Fra*_*une 2

我发现了我的问题。@trailmax 是正确的(在对他自己的答案的评论中),我周围有圈养依赖项。

该错误实际上存在于我的问题中配置依赖项注入的代码片段中ConnectUserManager

Container.RegisterType<ConnectUserManager>(
    new PerRequestLifetimeManager(),
    new InjectionConstructor(
        Container.Resolve<ConnectDbContext>(),
        Container.Resolve<ITemplateManager>(),
        Settings.MaxFailedAccessAttemptsBeforeLockout,
        Settings.AccountLockoutTimeSpan));
Run Code Online (Sandbox Code Playgroud)

与以下版本不同,这会在此时此地解决一次ConnectDbContext依赖关系:

Container.RegisterType<ConnectUserManager>(
    new PerRequestLifetimeManager(),
    new InjectionFactory(
        container => new ConnectUserManager(
            container.Resolve<ConnectDbContext>(),
            container.Resolve<ITemplateManager>(),
            Settings.MaxFailedAccessAttemptsBeforeLockout,
            Settings.AccountLockoutTimeSpan)));
Run Code Online (Sandbox Code Playgroud)

每次ConnectUserManager构建新的依赖项时,它都会正确解析依赖项。

  • 所以毕竟存在生命周期问题! (2认同)