Pergunta

Eu estou construindo um projeto no EF6 e aspnet Identidade.

Eu estou enfrentando o seguinte problema:

se eu chamar

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

Recebo a conta que eu estou procurando (exemplo:isConfirmed = true).

Quando eu alterar manualmente um valor em meu banco de dados (isConfirmed = true -> isConfirmed = false) e que executar a consulta novamente, eu ainda tenho a minha conta antiga objeto (isConfirmed = true)

var account = await FindByNameAsync(userName); // Should be account.IsConfirmed = false, but still gives me IsConfirmed = true

Eu tentei adicionar o seguinte no meu construtor DbContext

> this.Configuration.ProxyCreationEnabled = false;
> this.Configuration.LazyLoadingEnabled = false;

Mas isso não muda nada.

O que posso fazer sobre isso?Quanto tempo o cache de dados permanecem?Todos os posts que eu vi, exigem que você execute a consulta (a partir de ..em ..), mas vendo como estou usando aspnet Identidade e eu não tenho nenhum controle sobre essas coisas, o que posso fazer?

Obrigado!

EDITAR:adicionado dbContext informações

Meu Coi (Unidade)

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

Meu IUnitOfWork

public interface IUnitOfWork : IDisposable
{
    void Save();
    Task SaveAsync();
    DbSet<TEntity> EntitySet<TEntity>() where TEntity : class;
    void MarkAsModified<TEntity>(TEntity entity) where TEntity : class;
}

Meu 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;
    }
}

ATUALIZAÇÃO:

Eu descobri outra coisa estranha.Quando eu definir o meu último login campo de data, de que a mudança se apanhada, mas quando eu definir o meu isConfirmed campo, que não são apanhados..(o DB realmente fica atualizados pelos dados armazenados em cache!

Portanto, isso confirma que os dados inseridos por meio do código persistentes, mas alterações manuais no DB se ignorado.

ATUALIZAÇÃO 2 No caso de alguém tem este problema:o problema não foi aspnet Identidade, é EF.

O que eu fiz foi implementado o meu próprio userstore e manualmente acessado EF e usados .AsNoTracking() para evitar o armazenamento em cache.

Foi útil?

Solução

HttpContext.A corrente é o mal em programação Assíncrona.

Síncrona ou código anterior seria apenas métodos de execução de um contexto e de um controlador por thread.Portanto, não houve conflito.

Na programação assíncrona, métodos de múltiplas instâncias do controlador são executadas no mesmo thread.Portanto, o valor de HttpContext.Atual não é o mesmo como você pensa, ele é sujo !!!

Em vez disso, você deve preservar a sua HttpContext e usá-lo dentro de seu código assíncrono, conforme mostrado abaixo.

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

Velho E Simples De Herança

Eu recomendo usar entidade abstrata controlador de padrão, que é de fácil utilização em modo assíncrono.

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

Derivar o seu controlador, assim como,

public class UserController : EntityController<UserManagementContext>
{


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

}

Se você ainda deseja usar a Unidade, em seguida, você terá que criar nova unidade instância por solicitação, mas que é apenas desperdício de ciclo de CPU.Na minha opinião, usar o Unity com o MVC para simplificar a tarefa é um pouco mais de programação.Se algo que é facilmente feito com classes abstratas.Programação assíncrona tem muitas coisas novas, a Unidade não foi projetada para isso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top