我们在ASP.NET MVC 5.2,Entity Framework 6.2和Unity 5.7中使用ASP.NET Identity 2.2。
我们有一个类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));
当我们需要显示给定用户的详细信息时,控制器操作将检索用户:
public async Task<ActionResult> Details(int id)
{
var user = await UserManager.FindByIdAsync(id);
...
}
其中UserManager
是注入属性:
[Dependency]
public ConnectUserManager UserManager { get; set; }
问题是user
似乎来自缓存:数据库中的修改似乎对我们的应用程序显示的内容没有任何影响。
此代码已投入生产一年,我们从未遇到任何问题:当我们的代码修改用户时,缓存似乎无效。
我们现在才注意到这个问题,因为当Identity将用户锁定时,它会更新用户的LockoutEndDateUtc
属性,但似乎没有使缓存失效,我们得到一个陈旧的LockoutEndDateUtc
值我们的展示。
我们做错了什么?
修改:
除非我遗漏了某些内容,否则所接受的解决方案(无论如何写作)似乎与原始海报和我的问题完全无关。
然而,原始海报似乎自己找到了(a?)解决方案:&#34;我所做的是实现了我自己的用户界面并手动访问EF并使用.AsNoTracking()来避免缓存。&# 34;
有没有办法在不必重新实现(或子类化)用户存储的情况下执行此操作?
答案 0 :(得分:1)
这是EF侥幸。身份没有任何内置缓存。
我怀疑你ConnectDbContext
的生命时间镜是依赖的,而非每个请求。
一旦ConnectDbContext
的实例返回实例o ApplicationUser
,会发生什么。然后另一个ConnectDbContext
实例执行锁定。但是当你回到ConnectDbContext
的第一个实例时,它对其他东西所做的更新一无所知。因此,当您第二次获得相同的实例时,它不会进入数据库,它会返回已经跟踪过该用户的实例。
解决此问题的方法 - 确保您的生命周期范围与所涉及的所有活动部件相匹配:ConnectUserManager
,UserStore
和ConnectDbContext
。因此,无论何时从DB获取对象,它始终都是ConnectDbContext
的同一个实例,为您提供此功能。
也是你链接的答案 - 看到最后的评论,OP说他有同样的范围问题。
答案 1 :(得分:1)
我发现了我的问题。 @trailmax是正确的(在他自己的回答的评论中),我有俘虏的依赖关系。
该错误实际上来自我的问题的代码片段,用于配置ConnectUserManager
依赖项的注入:
Container.RegisterType<ConnectUserManager>(
new PerRequestLifetimeManager(),
new InjectionConstructor(
Container.Resolve<ConnectDbContext>(),
Container.Resolve<ITemplateManager>(),
Settings.MaxFailedAccessAttemptsBeforeLockout,
Settings.AccountLockoutTimeSpan));
与以下版本不同,此功能可以解决ConnectDbContext
依赖关系一次:
Container.RegisterType<ConnectUserManager>(
new PerRequestLifetimeManager(),
new InjectionFactory(
container => new ConnectUserManager(
container.Resolve<ConnectDbContext>(),
container.Resolve<ITemplateManager>(),
Settings.MaxFailedAccessAttemptsBeforeLockout,
Settings.AccountLockoutTimeSpan)));
正确解析依赖关系每次构建新的ConnectUserManager
。