Entity Framework Aggiorna contesto?


101

Come potrei aggiornare il mio contesto? Ho entità basate su viste dal mio database e quando ho effettuato un aggiornamento su una tabella Entità che ha proprietà di navigazione per le viste, l'entità viene aggiornata ma la vista non si aggiorna secondo i nuovi aggiornamenti ... voglio solo tornare da il Db i dati. Grazie!

Risposte:


92

Il modo migliore per aggiornare le entità nel tuo contesto è eliminare il tuo contesto e crearne uno nuovo.

Se hai davvero bisogno di aggiornare qualche entità e stai usando l'approccio Code First con la classe DbContext, puoi usare

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

Per ricaricare le proprietà di navigazione della raccolta, puoi usare

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

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


3
Non riesco a farlo funzionare per ricaricare le proprietà di navigazione figlio.
Paul,

@David puoi usare context.ReloadNavigationProperty(parent, p => p.Children);se haiclass Parent { ICollection<Child> Children; }
Jinjinov

In EF Core puoi usare Query (). Load () così, ad esempiocontext.Entry(order).Collection(o => o.NavigationProperty).Query().Load();
Rubenisme

Non capisco perché questa soluzione sia votata così bene. context.Entry (entity) .Collection <TElement> (navigationProperty) .Query () non ricarica la raccolta figlio. Ti dà solo un Iqueryable che rappresenta la query utilizzata per ottenere la raccolta. Non fa letteralmente nulla.
statler

72
yourContext.Entry(yourEntity).Reload();

3
Grazie per la semplice soluzione. Non vedo la necessità di incapsulare questo in un metodo di estensione come ha fatto RX_DID_RX
Thomas

Questo è stato un vero toccasana per me. Grazie!
Kevin

19
Si noti che questo non ricarica le proprietà di navigazione della raccolta, ma solo la voce dell'entità stessa.
James Wilkins,

28

Se vuoi ricaricare entità specifiche, con DbContextApi, RX_DID_RX ti ha già dato la risposta.

Se vuoi ricaricare / aggiornare tutte le entità che hai caricato:

Se stai usando Entity Framework 4.1+ (EF5 o EF 6 probabilmente), API DbContext:

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

Se stai 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);
}

Il miglior consiglio comunque è, cerca di usare un "contesto di breve durata" ed eviterai questo tipo di problemi.

Ho scritto un paio di articoli sull'argomento:

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


Ben fatto!! Mi ha salvato la giornata!
Radu D

15

Usa il metodo Aggiorna :

context.Refresh(RefreshMode.StoreWins, yourEntity);

o in alternativa elimina il tuo contesto attuale e creane uno nuovo.


@JMK Cosa non funziona esattamente qui? Sembra funzionare bene per me (EF 6.1.1).
Sebastian Krysmanski

@SebastianKrysmanski ho commentato quasi un anno fa, forse è stato corretto da allora?
JMK

5
Penso che funzioni solo per objectcontext ma non per dbcontext. È necessaria una conversazione tra loro
batmaci

3
@batmaci Che può essere facilmente fatto con((IObjectContextAdapter)dbContext).ObjectContext
Daniel Z.

3
Che non è stato dichiarato in modo un po 'incompleto.
user441521

6

context.Reload () non funzionava per me in MVC 4, EF 5, quindi l'ho fatto.

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

e funziona bene.


1

EF 6

Nel mio scenario, Entity Framework non stava raccogliendo i dati appena aggiornati. Il motivo potrebbe essere che i dati sono stati aggiornati al di fuori del suo ambito. L'aggiornamento dei dati dopo il recupero ha risolto il mio 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);
}

1
Sono con EF6. Perché questo è meglio di un _context.Entry(entity).Reload();?
Csaba Toth,

Per quanto posso ricordare, .Reload()non è disponibile in EF6. @CsabaToth
Mahbubur Rahman

0

L'aggiornamento del contesto del database con Ricarica non è consigliato a causa della perdita di prestazioni. È abbastanza buono e la procedura migliore per inizializzare una nuova istanza di dbcontext prima di ogni operazione eseguita. Fornisce inoltre un contesto aggiornato aggiornato per ciascuna operazione.

using (YourContext ctx = new YourContext())
{
   //Your operations
}

6
Amico ... Scaricare il tuo contesto ogni volta aggiornerà anche le cose che non vuoi vengano aggiornate, il che porterà davvero a problemi di prestazioni.
LuckyLikey

2
Questa è un'idea terribile in quanto influisce sulla capacità di scrivere test unitari. Se il tuo codice si spegne e le notizie su un nuovo contesto, come funzionerà durante uno unit test?
vincitore

5
Sarebbe utile per me e per altri se mostrassi alcuni campioni piuttosto che fare critiche.
AOG

Va bene per piccoli siti web.
alikuli

-7

Mi sono fatto male alla testa per niente! La risposta è stata molto semplice, sono appena tornato alle basi ...

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

aggiungi questa riga di seguito dopo aver aggiornato / eliminato: stai ricaricando la tua entità, senza metodi di sistema fantasiosi.

e2 = new some_Entities(); //reset.

2
Questo "funzionerà" - è solo un'idea terribile e avrà altre conseguenze
Adam Hey,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.