gpt4 book ai didi

c# - aspnet Identity 中的 Entity Framework 缓存

转载 作者:行者123 更新时间:2023-11-30 22:10:09 24 4
gpt4 key购买 nike

我正在 EF6 和 aspnet Identity 中构建一个项目。

我遇到了以下问题:

如果我打电话

var account = await FindByNameAsync(userName); // account.IsConfirmed = true

我得到了我正在寻找的帐户(例如:isConfirmed = true)。

当我手动更改数据库中的值 (isConfirmed = 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;

但这并没有改变任何东西。

我该怎么办?缓存数据保留多长时间?我看到的所有帖子都要求您运行查询(从 .. in ..),但是看到我如何使用 aspnet Identity 并且我无法控制这些事情,我该怎么办?

谢谢!

编辑:添加了 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;
}

我的用户管理上下文

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 字段时,它没有被拾取..(数据库更改实际上被缓存数据覆盖!

因此这证实了通过代码输入的数据得到了持久化,但数据库中的手动更改被忽略了。

更新 2如果有人也有这个问题:问题不是 aspnet Identity,而是 EF。

我所做的是实现我自己的用户存储并手动访问 EF 并使用 .AsNoTracking() 来避免缓存。

最佳答案

HttpContext.Current 在异步编程中是邪恶的。

同步或更早的代码只会在每个线程执行一个上下文和一个 Controller 的方法。所以没有冲突。

在异步编程中,多个 Controller 实例的方法在同一个线程上执行。所以 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));

普通的旧继承

我建议使用抽象实体 Controller 模式,它在异步模式下很容易使用。

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

相应地派生您的 Controller ,例如,

public class UserController : EntityController<UserManagementContext>
{


public async Task<ActionResult> SomeMethod(){
......
var user = await DB.FindByNameAsync(userName);
......
}

}

如果您仍想使用 Unity,则必须为每个请求创建新的 unity 实例,但这只是浪费 CPU 周期。在我看来,在 MVC 中使用 Unity 来完成更简单的任务只是编程。如果使用抽象类可以轻松完成某些事情。异步编程有很多新东西,Unity 不是为此而设计的。

关于c# - aspnet Identity 中的 Entity Framework 缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21041352/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com