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.