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!

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ć


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

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/


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.


@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.


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

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
}

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.

2
To „zadziała” - to po prostu okropny pomysł i będzie miał inne konsekwencje
— Adam Hey
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.