在ASPNET身份中的实体框架缓存
-
21-12-2019 - |
题
我在EF6和ASPNET身份中构建一个项目。
我面临以下问题:
如果我打电话
var account = await FindByNameAsync(userName); // account.IsConfirmed = true
.
我得到了我正在寻找的帐户(例如:isconfirmed= true)。
当我手动更改我的数据库中的值(iscrunfirmed= true - > iSconfirmed= false)并且我再次运行我的查询,我仍然会得到我的旧帐户对象(Isconfirmed= true)
var account = await FindByNameAsync(userName); // Should be account.IsConfirmed = false, but still gives me IsConfirmed = true
.
我尝试在我的dbcontext构造函数中添加以下内容
> this.Configuration.ProxyCreationEnabled = false;
> this.Configuration.LazyLoadingEnabled = false;
.
但这没有改变任何东西。
我该怎么办?缓存数据保留多长时间? 我见过的所有帖子都要求您运行查询(从......中),但看到我如何使用ASPNet身份,我无法控制这些东西,我该怎么办?
谢谢!
编辑:添加dbcontext信息
我的ioc(unity)
container.RegisterType<IUnitOfWork, UserManagementContext>(new HttpContextLifetimeManager<IUnitOfWork>());
container.RegisterType<IUserStore<Account>, UserStore<Account>>(new InjectionConstructor(container.Resolve<IUnitOfWork>()));
.
httpcontextlifetimemanager:
public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
{
public override object GetValue()
{
return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];
}
public override void SetValue(object newValue)
{
HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = newValue;
}
public override void RemoveValue()
{
HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);
}
public void Dispose()
{
RemoveValue();
}
}
.
我的iunitofwork
public interface IUnitOfWork : IDisposable
{
void Save();
Task SaveAsync();
DbSet<TEntity> EntitySet<TEntity>() where TEntity : class;
void MarkAsModified<TEntity>(TEntity entity) where TEntity : class;
}
.
我的usermanagementcontext
public class UserManagementContext : IdentityDbContext<Account>, IUnitOfWork
{
static UserManagementContext()
{
//Database.SetInitializer<UserManagementContext>(new RecreateDatabase());
Database.SetInitializer<UserManagementContext>(null);
}
public UserManagementContext()
: base("Name=UserManagementConnection")
{
this.Configuration.ProxyCreationEnabled = false;
this.Configuration.LazyLoadingEnabled = false;
}
// ... (my Dbsets)
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// configuration ..
}
public void Save()
{
SaveChanges();
}
public async Task SaveAsync()
{
await SaveChangesAsync();
}
public DbSet<TEntity> EntitySet<TEntity>() where TEntity : class
{
return this.Set<TEntity>();
}
public void MarkAsModified<TEntity>(TEntity entity) where TEntity : class
{
this.Entry(entity).State = EntityState.Modified;
}
}
.
更新:
我发现了另一个奇怪的事情。当我设置上次登录日期字段时,将更改拾取,但是当我设置我的Isconfirmed字段时,不会被拾取。(DB更改实际上由缓存数据覆盖!
所以这确实证实,通过代码输入的数据持续存在,但DB的手动更改被忽略。
更新2 如果有人有这个问题:问题不是阿斯卡网身份,它是EF。
我所做的是我自己的usserstore,手动访问了EF并使用.asnotracking()以避免缓存。
解决方案
httpcontext.current是异步编程中的邪恶。
同步或更早的代码只能执行每个线程的一个上下文的方法和一个控制器。所以没有冲突。
在异步编程中,在同一线程上执行多个控制器实例的方法。所以HttpContext.Current的价值与您的想法不一样,它很脏!!!
相反,您应该保留您的HTTPContext,并在异步代码中使用它,如下所示。
public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
{
private HttpContext Context;
public HttpContextLifetimeManager(HttpContext context){
this.Context = context;
}
public override object GetValue()
{
return Context.Items[typeof(T).AssemblyQualifiedName];
}
public override void SetValue(object newValue)
{
Context.Items[typeof(T).AssemblyQualifiedName] = newValue;
}
public override void RemoveValue()
{
Context.Items.Remove(typeof(T).AssemblyQualifiedName);
}
public void Dispose()
{
RemoveValue();
}
}
container.RegisterType<IUnitOfWork, UserManagementContext>(
new HttpContextLifetimeManager<IUnitOfWork>(this.ControllerContext.HttpContext));
.
纯旧继承
我建议使用抽象实体控制器模式,这易于在异步模式中使用。
public abstract class EntityController<TDbContext> : Controller
where TDbContext: DbContext
{
protected TDbContext DB { get; private set;}
public EntityController(){
DB = Activator.CreateInstance<TDbContext>();
}
protected override void OnDispose(){
DB.Dispose();
}
}
.
相应地导出您的控制器,
public class UserController : EntityController<UserManagementContext>
{
public async Task<ActionResult> SomeMethod(){
......
var user = await DB.FindByNameAsync(userName);
......
}
}
.
如果您仍然希望使用Unity,那么您必须每请求创建新的Unity实例,但这只是CPU周期的浪费。在我看来,在MVC中使用Unity进行简单任务即可刚刚编程。如果是用抽象课程轻松完成的东西。异步编程有很多新事物,没有为此设计统一。