Contexto de atualização do Entity Framework?

100

Como posso atualizar meu contexto? Eu tenho entidades baseadas em visualizações de meu banco de dados e quando fiz uma atualização em uma tabela Entity que tem propriedades de navegação para visualizações, a entidade é atualizada, mas a visualização não atualiza de acordo com as novas atualizações ... só quero obter novamente de o Db os dados. Obrigado!

user2528557
fonte

Respostas:

91

A melhor maneira de atualizar entidades em seu contexto é descartar seu contexto e criar um novo.

Se você realmente precisa atualizar alguma entidade e está usando a abordagem Code First com a classe DbContext, você pode usar

    public static void ReloadEntity<TEntity>(
        this DbContext context, 
        TEntity entity)
        where TEntity : class
    {
        context.Entry(entity).Reload();
    }

Para recarregar as propriedades de navegação da coleção, você pode usar

    public static void ReloadNavigationProperty<TEntity, TElement>(
        this DbContext context, 
        TEntity entity, 
        Expression<Func<TEntity, ICollection<TElement>>> navigationProperty)
        where TEntity : class
        where TElement : class
    {
        context.Entry(entity).Collection<TElement>(navigationProperty).Query();
    }

Referência: https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbentityentry.reload(v=vs.113).aspx#M:System.Data.Entity.Infrastructure.DbEntityEntry .Recarregar

RX_DID_RX
fonte
3
Não consigo fazer isso funcionar para recarregar as propriedades de navegação filho.
Paul
@David você pode usar context.ReloadNavigationProperty(parent, p => p.Children);se tiverclass Parent { ICollection<Child> Children; }
Jinjinov
No EF Core você pode usar Query (). Load () então por exemplocontext.Entry(order).Collection(o => o.NavigationProperty).Query().Load();
Rubenisme
Não compreendo porque é que esta solução foi tão bem votada. context.Entry (entity) .Collection <TElement> (navigationProperty) .Query () não recarrega a coleção filho. Fornece apenas um Iqueryable que representa a consulta usada para obter a coleção. Literalmente não faz nada.
statler
72
yourContext.Entry(yourEntity).Reload();
kravits88
fonte
3
Obrigado pela solução fácil. Não vejo a necessidade de encapsular isso em um método de extensão como RX_DID_RX fez
Thomas
Este foi um salva-vidas para mim. Obrigado!
Kevin
19
Observe que isso não recarrega as propriedades de navegação da coleção, apenas a própria entrada da entidade.
James Wilkins
28

Se você deseja recarregar entidades específicas, com o DbContextApi, RX_DID_RX já deu a resposta.

Se você deseja recarregar / atualizar todas as entidades carregadas:

Se você estiver usando o Entity Framework 4.1+ (EF5 ou EF 6 provavelmente), API DbContext:

public void RefreshAll()
{
     foreach (var entity in ctx.ChangeTracker.Entries())
     {
           entity.Reload();
     }
}

Se você estiver usando entityFramework 4 (ObjectContext API):

public void RefreshAll()
{
     // Get all objects in statemanager with entityKey
     // (context.Refresh will throw an exception otherwise)
     var refreshableObjects = (from entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted
                                               | EntityState.Modified
                                               | EntityState.Unchanged)
                                      where entry.EntityKey != null
                                      select entry.Entity);

     context.Refresh(RefreshMode.StoreWins, refreshableObjects);
}

De qualquer maneira, o melhor conselho é tentar usar um "contexto de vida curta" e você evitará esse tipo de problema.

Escrevi alguns artigos sobre o assunto:

https://christianarg.wordpress.com/2013/06/13/entityframework-refreshall-loaded-entities-from-database/

Christian Rodriguez
fonte
Agradável!! Salvei meu dia!
Radu D
15

Use o método Refresh :

context.Refresh(RefreshMode.StoreWins, yourEntity);

ou, em alternativa, descarte seu contexto atual e crie um novo.

Alberto
fonte
@JMK O que exatamente não funciona aqui? Parece funcionar bem para mim (EF 6.1.1).
Sebastian Krysmanski,
@SebastianKrysmanski Comentei há quase um ano, talvez tenha sido corrigido desde então?
JMK de
5
Acho que funciona apenas para objectcontext, mas não para dbcontext. É necessária uma conversa entre eles
batmaci
3
@batmaci O que pode ser facilmente feito com((IObjectContextAdapter)dbContext).ObjectContext
Daniel Z.
3
O que não foi declarado tão incompleto.
user441521
6

context.Reload () não estava funcionando para mim no MVC 4, EF 5, então fiz isso.

context.Entry(entity).State = EntityState.Detached;
entity = context.Find(entity.ID);

e está funcionando bem.

Chaudhary Kaleem Ahmad
fonte
1

EF 6

Em meu cenário, o Entity Framework não estava pegando os dados recém-atualizados. O motivo pode ser os dados foram atualizados fora de seu escopo. Atualizar os dados após a busca resolveu meu problema.

private void RefreshData(DBEntity entity)
{
    if (entity == null) return;

    ((IObjectContextAdapter)DbContext).ObjectContext.RefreshAsync(RefreshMode.StoreWins, entity);
}

private void RefreshData(List<DBEntity> entities)
{
    if (entities == null || entities.Count == 0) return;

    ((IObjectContextAdapter)DbContext).ObjectContext.RefreshAsync(RefreshMode.StoreWins, entities);
}
Mahbubur Rahman
fonte
1
Estou com EF6. Por que isso é melhor do que um _context.Entry(entity).Reload();?
Csaba Toth
Pelo que me lembro, .Reload()não está disponível no EF6. @CsabaToth
Mahbubur Rahman
0

Atualizar o contexto do banco de dados com Reload não é a maneira recomendada devido à perda de desempenho. É bom o suficiente e a melhor prática inicializar uma nova instância do dbcontext antes de cada operação executada. Ele também fornece um contexto atualizado e atualizado para cada operação.

using (YourContext ctx = new YourContext())
{
   //Your operations
}
aog
fonte
6
Cara .. Tirar seu contexto toda vez também irá atualizar as coisas que você não quer que sejam atualizadas, o que realmente levará a Problemas de Desempenho.
LuckyLikey
2
Esta é uma ideia terrível, pois afeta a capacidade de escrever testes de unidade. Se seu código disparar e criar um novo contexto, como isso funcionará durante um teste de unidade?
vencedor em
5
Seria útil para mim e para outros se você mostrasse alguns exemplos em vez de fazer críticas.
aog
É bom para sites pequenos.
alikuli
-7

Eu fiz minha própria cabeça doer por nada! A resposta foi muito simples - acabei de voltar ao básico ...

some_Entities   e2 = new some_Entities(); //your entity.

adicione esta linha abaixo depois de atualizar / excluir - você está recarregando sua entidade - sem métodos de sistema sofisticados.

e2 = new some_Entities(); //reset.
buffy555
fonte
2
Isso vai "funcionar" - é apenas uma ideia terrível e terá outras consequências
Adam Hey