C# aspnet标识中的实体框架缓存
我正在EF6和aspnet Identity中构建一个项目 我面临以下问题: 如果我打电话C# aspnet标识中的实体框架缓存,c#,.net,entity-framework,caching,asp.net-identity,C#,.net,Entity Framework,Caching,Asp.net Identity,我正在EF6和aspnet Identity中构建一个项目 我面临以下问题: 如果我打电话 var account = await FindByNameAsync(userName); // account.IsConfirmed = true 我得到了我正在寻找的帐户(例如:isConfirmed=true) 当我手动更改数据库中的值(isConfirmed=true->isConfirmed=false)并再次运行查询时,我仍然会得到我的旧帐户对象(isConfirmed=true) 我尝
var account = await FindByNameAsync(userName); // account.IsConfirmed = true
我得到了我正在寻找的帐户(例如:isConfirmed=true)
当我手动更改数据库中的值(isConfirmed=true->isConfirmed=false)并再次运行查询时,我仍然会得到我的旧帐户对象(isConfirmed=true)
我尝试在DbContext构造函数中添加以下内容
> this.Configuration.ProxyCreationEnabled = false;
> this.Configuration.LazyLoadingEnabled = false;
但这并没有改变任何事情
我能做些什么?缓存的数据保留多长时间?
我看到的所有帖子都要求您运行查询(from..in..),但是看到我如何使用aspnet Identity,而我无法控制这些事情,我该怎么办
谢谢
编辑:添加了dbContext信息
我的国际奥委会(团结)
container.RegisterType(新的HttpContextLifetimeManager());
RegisterType(新的InjectionConstructor(container.Resolve());
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();
}
}
公共类HttpContextLifetimeManager:LifetimeManager,IDisposable
{
公共重写对象GetValue()
{
返回HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];
}
公共覆盖无效设置值(对象新值)
{
HttpContext.Current.Items[typeof(T).AssemblyQualifiedName]=newValue;
}
public override void RemoveValue()
{
HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);
}
公共空间处置()
{
RemoveValue();
}
}
我的工作
public interface IUnitOfWork : IDisposable
{
void Save();
Task SaveAsync();
DbSet<TEntity> EntitySet<TEntity>() where TEntity : class;
void MarkAsModified<TEntity>(TEntity entity) where TEntity : class;
}
公共接口IUnitOfWork:IDisposable
{
作废保存();
任务SaveAsync();
DbSet EntitySet(),其中tenty:class;
无效标记修改(TEntity实体),其中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;
}
}
公共类UserManagementContext:IdentityDbContext,IUnitOfWork
{
静态UserManagementContext()
{
//SetInitializer(新的重新创建数据库());
Database.SetInitializer(null);
}
公共用户管理上下文()
:base(“Name=UserManagementConnection”)
{
this.Configuration.ProxyCreationEnabled=false;
this.Configuration.LazyLoadingEnabled=false;
}
//…(我的数据库集)
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
//配置。。
}
公共作废保存()
{
保存更改();
}
公共异步任务SaveAsync()
{
等待SaveChangesSync();
}
public DbSet EntitySet(),其中tenty:class
{
返回这个.Set();
}
公共无效标记已修改(TEntity实体),其中TEntity:类
{
this.Entry(entity).State=EntityState.Modified;
}
}
更新:
我发现了另一件奇怪的事。当我设置“上次登录日期”字段时,该更改会被拾取,但当我设置“已确认”字段时,该更改不会被拾取。。(数据库更改实际上会被缓存的数据覆盖
因此,这确认了通过代码输入的数据会被持久化,但数据库中的手动更改会被忽略
更新2
如果有人也有这个问题:问题不是aspnet身份,而是EF
我所做的是实现我自己的userstore并手动访问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));
公共类HttpContextLifetimeManager:LifetimeManager,IDisposable
{
私有HttpContext上下文;
公共HttpContextLifetimeManager(HttpContext上下文){
this.Context=Context;
}
公共重写对象GetValue()
{
返回Context.Items[typeof(T).AssemblyQualifiedName];
}
公共覆盖无效设置值(对象新值)
{
Context.Items[typeof(T).AssemblyQualifiedName]=newValue;
}
public override void RemoveValue()
{
Context.Items.Remove(typeof(T).AssemblyQualifiedName);
}
公共空间处置()
{
RemoveValue();
}
}
container.RegisterType(
新的HttpContextLifetimeManager(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();
}
}
公共抽象类EntityController:控制器
其中TDbContext:DbContext
{
受保护的TDbContext数据库{get;private set;}
公共实体控制器(){
DB=Activator.CreateInstance();
}
受保护的覆盖无效OnDispose(){
DB.Dispose();
}
}
相应地导出控制器,如下所示:
public class UserController : EntityController<UserManagementContext>
{
public async Task<ActionResult> SomeMethod(){
......
var user = await DB.FindByNameAsync(userName);
......
}
}
公共类用户控制器:EntityController
{
公共异步任务方法(){
......
var user=await DB.FindByNameAsync(用户名);
......
}
}
如果您仍然想使用Unity,那么您必须为每个请求创建新的Unity实例,但这只是浪费CPU周期。在我看来,在MVC中使用Unity来完成更简单的任务只是过度编程。如果使用抽象类可以轻松完成一些事情。异步编程有很多新东西,Unity并不是为此而设计的。HFindByNameAsync看起来像什么?@AkashKava这是来自aspnet identity(=>UserManager)的函数您是为每个请求使用一个实例,还是为整个应用程序使用一个DbContext实例?DbSet的Find方法会在本地对象中缓存值,除非您明确清除它。这是实体框架的问题。我在一个请求的生命周期(MVC)中使用一个DbContext,可以吗
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);
......
}
}