Entity Framework Refresh Contexte?

101

Comment pourrais-je actualiser mon contexte? J'ai des entités basées sur des vues de ma base de données et lorsque j'ai effectué une mise à jour sur une table Entité qui a des propriétés de navigation vers les vues, l'entité est mise à jour mais la vue ne s'actualise pas selon les nouvelles mises à jour ... je veux juste obtenir à nouveau de le Db les données. Merci!

user2528557
la source

Réponses:

92

La meilleure façon d'actualiser les entités dans votre contexte est de disposer votre contexte et d'en créer un nouveau.

Si vous avez vraiment besoin d'actualiser une entité et que vous utilisez l'approche Code First avec la classe DbContext, vous pouvez utiliser

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

Pour recharger les propriétés de navigation de la collection, vous pouvez utiliser

    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éférence: https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbentityentry.reload(v=vs.113).aspx#M:System.Data.Entity.Infrastructure.DbEntityEntry .Recharger

RX_DID_RX
la source
3
Je ne parviens pas à faire fonctionner cela pour recharger les propriétés de navigation enfants.
Paul
@David, vous pouvez utiliser context.ReloadNavigationProperty(parent, p => p.Children);si vous avezclass Parent { ICollection<Child> Children; }
Jinjinov
Dans EF Core vous pouvez utiliser Query (). Load () donc par exemplecontext.Entry(order).Collection(o => o.NavigationProperty).Query().Load();
Rubenisme
Je ne comprends pas pourquoi cette solution est si votée. context.Entry (entity) .Collection <TElement> (navigationProperty) .Query () ne recharge pas la collection enfant. Il ne vous donne qu'un Iqueryable représentant la requête utilisée pour obtenir la collection. Cela ne fait littéralement rien.
statler le
72
yourContext.Entry(yourEntity).Reload();
kravits88
la source
3
Merci pour la solution simple. Je ne vois pas la nécessité d'encapsuler cela dans une méthode d'extension comme RX_DID_RX l'a fait
Thomas
Ce fut une bouée de sauvetage pour moi. Je vous remercie!
Kevin
19
Notez que cela ne recharge pas les propriétés de navigation de collection, uniquement l'entrée d'entité elle-même.
James Wilkins
28

Si vous souhaitez recharger des entités spécifiques, avec le DbContextApi, RX_DID_RX vous a déjà donné la réponse.

Si vous souhaitez recharger / actualiser toutes les entités que vous avez chargées:

Si vous utilisez Entity Framework 4.1+ (EF5 ou EF 6 probablement), API DbContext:

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

Si vous utilisez entityFramework 4 (API ObjectContext):

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

Le meilleur conseil de toute façon est d'essayer d'utiliser un "contexte de courte durée" et vous éviterez ce genre de problèmes.

J'ai écrit quelques articles sur le sujet:

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

Christian Rodriguez
la source
joli!! J'ai sauvé ma journée!
Radu D
15

Utilisez la méthode Refresh :

context.Refresh(RefreshMode.StoreWins, yourEntity);

ou en alternative, supprimez votre contexte actuel et créez-en un nouveau.

Alberto
la source
@JMK Qu'est-ce qui ne fonctionne pas exactement ici? Cela semble bien fonctionner pour moi (EF 6.1.1).
Sebastian Krysmanski
@SebastianKrysmanski J'ai commenté il y a près d'un an, peut-être que cela a été corrigé depuis?
JMK
5
Je pense que cela ne fonctionne que pour objectcontext mais pas pour dbcontext. Une conversation entre eux est requise
batmaci
3
@batmaci Ce qui peut facilement être fait avec((IObjectContextAdapter)dbContext).ObjectContext
Daniel Z.
3
Ce qui n'a pas été déclaré si un peu incomplet.
user441521 du
6

context.Reload () ne fonctionnait pas pour moi dans MVC 4, EF 5, alors je l'ai fait.

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

et son fonctionnement très bien.

Chaudhary Kaleem Ahmad
la source
1

EF 6

Dans mon scénario, Entity Framework ne récupérait pas les données nouvellement mises à jour. La raison pourrait être que les données ont été mises à jour en dehors de leur portée. L'actualisation des données après la récupération a résolu mon problème.

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
la source
1
Je suis avec EF6. Pourquoi est-ce mieux qu'un _context.Entry(entity).Reload();?
Csaba Toth le
Pour autant que je me souvienne, .Reload()n'est pas disponible dans EF6. @CsabaToth
Mahbubur Rahman
0

L'actualisation du contexte de base de données avec Recharger n'est pas recommandée en raison de la perte de performances. Il est suffisant et recommandé d'initialiser une nouvelle instance de dbcontext avant chaque opération exécutée. Il vous fournit également un contexte actualisé à jour pour chaque opération.

using (YourContext ctx = new YourContext())
{
   //Your operations
}
aog
la source
6
Mec .. Le vidage de votre contexte à chaque fois actualisera également les éléments que vous ne voulez pas actualiser, ce qui entraînera vraiment des problèmes de performances.
LuckyLikey
3
C'est une idée terrible car elle affecte la capacité d'écrire des tests unitaires. Si votre code se déclenche et crée un nouveau contexte, comment cela va-t-il fonctionner pendant un test unitaire?
victor
5
Ce serait utile pour moi et pour d'autres si vous montrez des échantillons plutôt que de faire des critiques.
aog le
C'est bien pour les petits sites Web.
alikuli
-1

En fait, je suggère de supprimer l'entité entière, et de la recréer en fonction de votre approche

Bayan Al_A6rsh
la source
-7

J'ai fait mal à ma tête pour rien! La réponse était très simple - je suis juste retourné à l'essentiel ...

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

ajoutez cette ligne ci-dessous après avoir mis à jour / supprimé - vous rechargez vos méthodes système d'entité sans fantaisie.

e2 = new some_Entities(); //reset.
buffy555
la source
3
Cela "fonctionnera" - c'est juste une idée terrible et aura d'autres conséquences
Adam Hey