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!

user2528557
quelle

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

RX_DID_RX
quelle
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();
kravits88
quelle
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/

Christian Rodriguez
quelle
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.

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

Chaudhary Kaleem Ahmad
quelle
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);
}
Mahbubur Rahman
quelle
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
}
aog
quelle
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.
buffy555
quelle
2
Das wird "funktionieren" - es ist nur eine schreckliche Idee und wird andere Konsequenzen haben
Adam Hey