Entity Framework Odśwież kontekst?

101

Jak mogę odświeżyć mój kontekst? Mam encje oparte na widokach z mojej bazy danych i kiedy dokonałem aktualizacji w jednej tabeli Jednostka, która ma właściwości nawigacji do widoków, jednostka jest aktualizowana, ale widok nie odświeża się zgodnie z nowymi aktualizacjami ... po prostu chcę uzyskać ponownie z Db dane. Dzięki!

user2528557
źródło

Odpowiedzi:

92

Najlepszym sposobem na odświeżenie jednostek w kontekście jest usunięcie kontekstu i utworzenie nowego.

Jeśli naprawdę potrzebujesz odświeżyć jakąś jednostkę i używasz podejścia Code First z klasą DbContext, możesz użyć

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

Aby ponownie wczytać właściwości nawigacji kolekcji, możesz użyć

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

Źródła: https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbentityentry.reload(v=vs.113).aspx#M:System.Data.Entity.Infrastructure.DbEntityEntry .Przeładować

RX_DID_RX
źródło
3
Nie mogę uruchomić tego, aby ponownie załadować właściwości nawigacji podrzędnej.
Paul
@David możesz użyć, context.ReloadNavigationProperty(parent, p => p.Children);jeśli maszclass Parent { ICollection<Child> Children; }
Jinjinov
W EF Core można użyć Query (). Load (), więc na przykładcontext.Entry(order).Collection(o => o.NavigationProperty).Query().Load();
Rubenisme
Nie rozumiem, dlaczego to rozwiązanie jest tak wysoko oceniane. context.Entry (entity) .Collection <TElement> (navigationProperty) .Query () nie ładuje ponownie kolekcji podrzędnej. Daje ci tylko Iqueryable reprezentujące zapytanie użyte do pobrania kolekcji. Dosłownie nic nie robi.
statler
72
yourContext.Entry(yourEntity).Reload();
kravits88
źródło
3
Dzięki za łatwe rozwiązanie. Nie widzę potrzeby hermetyzacji tego w metodzie rozszerzenia, takiej jak RX_DID_RX
Thomas
To było dla mnie uratowanie życia. Dziękuję Ci!
Kevin
19
Należy zauważyć, że nie powoduje to ponownego załadowania właściwości nawigacji kolekcji, tylko sam wpis jednostki.
James Wilkins
28

Jeśli chcesz ponownie załadować określone jednostki, z DbContextApi, RX_DID_RX już udzielił odpowiedzi.

Jeśli chcesz przeładować / odświeżyć wszystkie załadowane encje:

Jeśli używasz Entity Framework 4.1+ (prawdopodobnie EF5 lub EF 6), interfejs API DbContext:

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

Jeśli używasz 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);
}

W każdym razie najlepszą radą jest użycie „kontekstu krótkotrwałego”, a unikniesz tego rodzaju problemów.

Napisałem kilka artykułów na ten temat:

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

Christian Rodriguez
źródło
niezłe!! Uratowałem mój dzień!
Radu D,
15

Użyj metody Odśwież :

context.Refresh(RefreshMode.StoreWins, yourEntity);

lub alternatywnie pozbądź się obecnego kontekstu i utwórz nowy.

Alberto
źródło
@JMK Co tu właściwie nie działa? Wydaje mi się, że działa dobrze (EF 6.1.1).
Sebastian Krysmanski
@SebastianKrysmanski Komentowałem prawie rok temu, może od tego czasu zostało to naprawione?
JMK
5
Myślę, że działa tylko dla objectcontext, ale nie dla dbcontext. Wymagana jest rozmowa między nimi
batmaci
3
@batmaci Co można łatwo zrobić z((IObjectContextAdapter)dbContext).ObjectContext
Daniel Z.
3
Co nie zostało powiedziane jako trochę niepełne.
user441521
6

Context.Reload () nie działał dla mnie w MVC 4, EF 5, więc zrobiłem to.

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

i działa dobrze.

Chaudhary Kaleem Ahmad
źródło
1

EF 6

W moim scenariuszu Entity Framework nie odebrał nowo zaktualizowanych danych. Przyczyną może być aktualizacja danych poza jej zakresem. Odświeżenie danych po pobraniu rozwiązało mój problem.

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
źródło
1
Jestem z EF6. Dlaczego to jest lepsze niż _context.Entry(entity).Reload();?
Csaba Toth
O ile pamiętam, .Reload()nie jest dostępny w EF6. @CsabaToth
Mahbubur Rahman
0

Odświeżanie kontekstu bazy danych za pomocą funkcji Reload nie jest zalecane ze względu na utratę wydajności. Jest to wystarczająco dobre i najlepsze rozwiązanie, aby zainicjować nowe wystąpienie kontekstu dbcontext przed każdą wykonywaną operacją. Zapewnia również odświeżony, aktualny kontekst dla każdej operacji.

using (YourContext ctx = new YourContext())
{
   //Your operations
}
aog
źródło
6
Koleś ... Zrzucanie kontekstu za każdym razem odświeży również rzeczy, których nie chcesz, aby były odświeżane, co naprawdę doprowadzi do problemów z wydajnością.
LuckyLikey
2
To okropny pomysł, ponieważ wpływa na możliwość pisania testów jednostkowych. Jeśli twój kod zepsuje się i wyświetli nowy kontekst, jak to będzie działać podczas testu jednostkowego?
zwycięzca
5
Byłoby użyteczne dla mnie i innych, gdybyś pokazał kilka próbek zamiast krytykować.
aog
Jest w porządku dla małych witryn internetowych.
alikuli,
-7

Z powodu niczego nie bolała mnie głowa! Odpowiedź była bardzo prosta - właśnie wróciłem do podstaw ...

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

dodaj tę linię poniżej po zaktualizowaniu / usunięciu - ponownie ładujesz swoją jednostkę - bez wymyślnych metod systemowych.

e2 = new some_Entities(); //reset.
buffy555
źródło
2
To „zadziała” - to po prostu okropny pomysł i będzie miał inne konsekwencje
Adam Hey