Entity Framework Kontext aktualisieren?


100

Wie könnte ich meinen Kontext aktualisieren? Ich habe Entitäten, die auf Ansichten aus meiner Datenbank basieren, und wenn ich eine Aktualisierung über eine Tabellenentität vorgenommen habe, die über Navigationseigenschaften für Ansichten verfügt, wird die Entität aktualisiert, aber die Ansicht wird nicht entsprechend den neuen Aktualisierungen aktualisiert. Ich möchte nur erneut von die Db die Daten. Vielen Dank!

Antworten:


91

Der beste Weg, um Entitäten in Ihrem Kontext zu aktualisieren, besteht darin, Ihren Kontext zu entsorgen und einen neuen zu erstellen.

Wenn Sie eine Entität wirklich aktualisieren müssen und den Code First-Ansatz mit der DbContext-Klasse verwenden, können Sie ihn verwenden

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

Sie können die Navigationseigenschaften der Sammlung neu laden

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

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


3
Ich kann dies nicht zum Laufen bringen, um untergeordnete Navigationseigenschaften neu zu laden.
Paul

@ David können Sie verwenden, context.ReloadNavigationProperty(parent, p => p.Children);wenn Sie habenclass Parent { ICollection<Child> Children; }
Jinjinov

In EF Core können Sie beispielsweise Query (). Load () verwendencontext.Entry(order).Collection(o => o.NavigationProperty).Query().Load();
Rubenisme

Ich verstehe nicht, warum diese Lösung so hoch gewählt wird. context.Entry (entity) .Collection <TElement> (navigationProperty) .Query () lädt die untergeordnete Sammlung nicht neu. Sie erhalten nur eine Iqueryable, die die Abfrage darstellt, mit der die Sammlung abgerufen wurde. Es macht buchstäblich nichts.
Statler

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

3
Danke für die einfache Lösung. Ich sehe keine Notwendigkeit darin, dies in einer Erweiterungsmethode wie RX_DID_RX zu kapseln
Thomas

Das war ein Lebensretter für mich. Danke dir!
Kevin

19
Beachten Sie, dass dadurch nicht die Eigenschaften der Sammlungsnavigation neu geladen werden, sondern nur der Entitätseintrag selbst.
James Wilkins

28

Wenn Sie bestimmte Entitäten mit DbContextApi neu laden möchten, hat RX_DID_RX Ihnen bereits die Antwort gegeben.

Wenn Sie alle geladenen Entitäten neu laden / aktualisieren möchten:

Wenn Sie Entity Framework 4.1+ verwenden (EF5 oder EF 6 wahrscheinlich), DbContext API:

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

Wenn Sie entityFramework 4 (ObjectContext API) verwenden:

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

Der beste Rat ist sowieso, versuchen Sie, einen "kurzlebigen Kontext" zu verwenden, und Sie werden diese Art von Problemen vermeiden.

Ich habe ein paar Artikel zu diesem Thema geschrieben:

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


Schön!! Rettete meinen Tag!
Radu D

15

Verwenden Sie die Aktualisierungsmethode :

context.Refresh(RefreshMode.StoreWins, yourEntity);

oder alternativ entsorgen Sie Ihren aktuellen Kontext und erstellen Sie einen neuen.


@JMK Was genau funktioniert hier nicht? Es scheint gut für mich zu funktionieren (EF 6.1.1).
Sebastian Krysmanski

@SebastianKrysmanski Ich habe vor fast einem Jahr kommentiert, vielleicht wurde es seitdem behoben?
JMK

5
Ich denke, dass es nur für Objektkontext funktioniert, aber nicht für Datenbankkontext. Ein Gespräch zwischen ihnen ist erforderlich
Batmaci

3
@ Batmaci Was leicht gemacht werden kann mit((IObjectContextAdapter)dbContext).ObjectContext
Daniel Z.

3
Was nicht so etwas unvollständig angegeben wurde.
user441521

6

context.Reload () hat in MVC 4, EF 5 nicht für mich funktioniert, also habe ich dies getan.

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

und es funktioniert gut.


1

EF 6

In meinem Szenario hat Entity Framework die neu aktualisierten Daten nicht erfasst. Der Grund könnte sein, dass die Daten außerhalb ihres Geltungsbereichs aktualisiert wurden. Das Aktualisieren von Daten nach dem Abrufen hat mein Problem behoben.

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
Ich bin bei EF6. Warum ist das besser als ein _context.Entry(entity).Reload();?
Csaba Toth

Soweit ich mich erinnern kann, .Reload()ist in EF6 nicht verfügbar. @CsabaToth
Mahbubur Rahman

0

Das Aktualisieren des Datenbankkontexts mit Reload wird aufgrund von Leistungseinbußen nicht empfohlen. Es ist gut genug und die beste Vorgehensweise, vor jeder ausgeführten Operation eine neue Instanz des Datenbankkontexts zu initialisieren. Außerdem erhalten Sie für jede Operation einen aktualisierten, aktuellen Kontext.

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

6
Alter .. Wenn Sie Ihren Kontext jedes Mal löschen, werden auch die Dinge aktualisiert, die Sie nicht aktualisieren möchten, was wirklich zu Leistungsproblemen führt.
LuckyLikey

2
Dies ist eine schreckliche Idee, da sie die Fähigkeit zum Schreiben von Komponententests beeinträchtigt. Wenn Ihr Code ausgeht und einen neuen Kontext aufzeigt, wie wird das während eines Komponententests funktionieren?
Sieger

5
Es wäre nützlich für mich und andere, wenn Sie einige Beispiele zeigen, anstatt Kritik zu üben.
aog

Es ist gut für kleine Websites.
Alikuli

-7

Ich habe meinen eigenen Kopf wegen nichts verletzt! Die Antwort war sehr einfach - ich bin gerade zu den Grundlagen zurückgekehrt ...

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

Fügen Sie diese Zeile unten hinzu, nachdem Sie sie aktualisiert / gelöscht haben - Sie laden Ihre Entität neu - keine ausgefallenen Systemmethoden.

e2 = new some_Entities(); //reset.

2
Das wird "funktionieren" - es ist nur eine schreckliche Idee und wird andere Konsequenzen haben
Adam Hey
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.