Como forçar o Entity Framework a sempre obter dados atualizados do banco de dados?

86

Estou usando a biblioteca EntityFramework.Extended para realizar atualizações em lote. O único problema é que o EF não mantém registro das atualizações em lote realizadas pela biblioteca. Portanto, quando eu consulto o DbContextnovamente, ele não retorna as entidades atualizadas.

Descobri que usar o AsNoTracking()método durante a consulta desativa o rastreamento e obtém dados novos do banco de dados. No entanto, como o EF não acompanha as entidades consultadas AsNoTracking(), não posso realizar nenhuma atualização nos dados consultados.

Existe alguma maneira de forçar o EF a obter os dados mais recentes enquanto rastreia as alterações?

Saravana
fonte
2
29 mil visualizações e apenas 19 votos positivos sobre isso ... bem, eu adicionei o meu mesmo assim
jleach

Respostas:

148

Tente isso para atualizar uma única entidade:

Context.Entry<T>(entity).Reload()

Editar: para obter dados novos para uma coleção de entidades, vale a pena tentar descartar a DbContextinstância após cada solicitação.

PlTaylor
fonte
Obrigado! Existe alguma maneira de recarregar uma coleção de entidades em vez de uma? De preferência todo DbSet.
Saravana
Precisa de mais alguma coisa para que esta seja considerada a resposta?
PlTaylor
1
Sim, ainda não mostra como recarregar uma coleção de entidades.
Saravana
1
Você já tentou descartar seu dbcontext e criar um novo?
PlTaylor
2
Levei horas para chegar a essa conclusão. Esse EDIT na resposta é o que me ajudou a encontrar minha solução. Obrigado!
BeemerGuy
17

Tropecei nessa questão enquanto procurava uma solução para um problema que estava tendo em que as propriedades de navegação não eram preenchidas após a atualização da entidade. Sempre que tentava recarregar a entidade do banco de dados, ele pegava a entrada do armazenamento local, o que não preenchia as propriedades de navegação por meio do carregamento lento. Em vez de destruir o contexto e recriar um, descobri que isso me permitiu obter dados novos com os proxies funcionando:

_db.Entry(entity).State = EntityState.Detached;

A lógica por trás disso era - minha atualização anexou a entidade para que rastreasse as alterações nela. Isso o adiciona ao armazenamento local. Depois disso, qualquer tentativa de recuperar a entidade com proxies funcionais resultaria em pegar o local em vez de ir para o banco de dados e retornar uma nova entidade habilitada para proxy. Tentei a opção recarregar acima, que atualiza o objeto do banco de dados, mas não fornece o objeto com proxy com carregamento lento. Tentei fazer um Find(id), Where(t => t.Id = id), First(t => t.Id = id). Por fim, verifiquei os estados disponíveis fornecidos e vi que havia um estado "Desanexado". Eureka! Espero que isso ajude alguém.

Zach
fonte
Onde você aplica o estado Desanexado para fazer o carregamento lento funcionar, por favor? Tentei sua solução e não funcionou para mim, devo ter perdido algo. Agradecemos sua ajuda
Rex
2
Eu descobri: 1. salve a entidade, 2. defina o estado como desanexado, 3. leia a entidade do banco de dados. Obrigado pela dica!
Rex
1

Fazer o código rodar no mesmo contexto não produzirá entidades atualizadas. Ele apenas acrescentará novas entidades criadas no banco de dados entre as execuções. O recarregamento de força EF pode ser feito assim:

ObjectQuery _query = Entity.MyEntity;
_query.MergeOption = MergeOption.OverwriteChanges;
var myEntity = _query.Where(x => x.Id > 0).ToList();
CodeMad
fonte
1

Eu declarei a variável de entidade, sem atribuição, como parte da classe. Isso me permitiu descartar uma instância sem perder a variável para referência por outros métodos. Acabei de encontrar isso, então não tem muito tempo de execução, mas até agora parece estar funcionando bem.

public partial class frmMyForm
{
    private My_Entities entity;

    public frmMyForm()
    {
        InitializeComponent();
    }

    private void SomeControl_Click(object sender, EventArgs e)
    {
        db.SaveChanges();
        db.Dispose();
        entity = new My_Entities();
        //more code using entity ...
}
Lambreta
fonte
0

Para mim ... eu acesso meu DbContext assim:

_viewModel.Repo.Context

Para forçar EF a atingir o banco de dados, eu faço o seguinte:

_viewModel.Repo.Context = new NewDispatchContext();

Substituindo o DbContext atual por uma nova instância. Então, da próxima vez que eu usar meus serviços de dados, eles obterão os dados do banco de dados.

pdschuller
fonte