Entity Framework ¿Actualizar el contexto?

101

¿Cómo puedo actualizar mi contexto? Tengo entidades basadas en vistas de mi base de datos y cuando realicé una actualización sobre una entidad de tabla que tiene propiedades de navegación para las vistas, la entidad se actualiza pero la vista no se actualiza de acuerdo con las nuevas actualizaciones ... solo quiero volver de la Db los datos. ¡Gracias!

usuario2528557
fuente

Respuestas:

92

La mejor manera de actualizar entidades en su contexto es disponer su contexto y crear uno nuevo.

Si realmente necesita actualizar alguna entidad y está utilizando el enfoque Code First con la clase DbContext, puede usar

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

Para recargar las propiedades de navegación de la colección, puede usar

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

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

RX_DID_RX
fuente
3
No puedo hacer que esto funcione para volver a cargar las propiedades de navegación secundaria.
Paul
@David puede usar context.ReloadNavigationProperty(parent, p => p.Children);si tieneclass Parent { ICollection<Child> Children; }
Jinjinov
En EF Core puede usar Query (). Load (), por ejemplocontext.Entry(order).Collection(o => o.NavigationProperty).Query().Load();
Rubenisme
No entiendo por qué se vota tanto esta solución. context.Entry (entidad) .Collection <TElement> (navigationProperty) .Query () no recarga la colección secundaria. Solo le brinda un Iqueryable que representa la consulta utilizada para obtener la colección. Literalmente no hace nada.
statler
72
yourContext.Entry(yourEntity).Reload();
kravits88
fuente
3
Gracias por la fácil solución. No veo la necesidad de encapsular esto en un método de extensión como lo hizo RX_DID_RX
Thomas
Esto fue un salvavidas para mí. ¡Gracias!
Kevin
19
Tenga en cuenta que esto no recarga las propiedades de navegación de la colección, solo la entrada de la entidad en sí.
James Wilkins
28

Si desea recargar entidades específicas, con el DbContextApi, RX_DID_RX ya le dio la respuesta.

Si desea recargar / actualizar todas las entidades que cargó:

Si está utilizando Entity Framework 4.1+ (EF5 o EF 6 probablemente), API DbContext:

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

Si está utilizando 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);
}

De todos modos, el mejor consejo es tratar de utilizar un "contexto de corta duración" y evitará este tipo de problemas.

Escribí un par de artículos sobre el tema:

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

Christian Rodríguez
fuente
¡¡Buena esa!! ¡Salvó mi día!
Radu D
15

Utilice el método Refresh :

context.Refresh(RefreshMode.StoreWins, yourEntity);

o, alternativamente, elimine su contexto actual y cree uno nuevo.

Alberto
fuente
@JMK ¿Qué es exactamente lo que no funciona aquí? Parece funcionar bien para mí (EF 6.1.1).
Sebastian Krysmanski
@SebastianKrysmanski Comenté hace casi un año, ¿tal vez se haya solucionado desde entonces?
JMK
5
Creo que funciona solo para objectcontext pero no dbcontext. Se requiere una conversación entre ellos
batmaci
3
@batmaci Que se puede hacer fácilmente con((IObjectContextAdapter)dbContext).ObjectContext
Daniel Z.17 de
3
Lo cual no fue dicho tan incompleto.
user441521
6

context.Reload () no funcionaba para mí en MVC 4, EF 5, así que hice esto.

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

y está funcionando bien.

Chaudhary Kaleem Ahmad
fuente
1

EF 6

En mi escenario, Entity Framework no estaba recogiendo los datos recién actualizados. La razón podría ser que los datos se actualizaron fuera de su alcance. Actualizar los datos después de obtenerlos resolvió mi problema.

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
fuente
1
Estoy con EF6. ¿Por qué es esto mejor que un _context.Entry(entity).Reload();?
Csaba Toth
Por lo que puedo recordar, .Reload()no está disponible en EF6. @CsabaToth
Mahbubur Rahman
0

No se recomienda actualizar el contexto de la base de datos con Reload debido a pérdidas de rendimiento. Es suficientemente bueno y la mejor práctica inicializar una nueva instancia de dbcontext antes de ejecutar cada operación. También le proporciona un contexto actualizado para cada operación.

using (YourContext ctx = new YourContext())
{
   //Your operations
}
aog
fuente
6
Amigo ... Vaciar tu contexto cada vez también actualizará las cosas que no quieres que se actualicen, lo que realmente conducirá a problemas de rendimiento.
LuckyLikey
2
Esta es una idea terrible, ya que afecta la capacidad de escribir pruebas unitarias. Si su código se dispara y las noticias muestran un nuevo contexto, ¿cómo va a funcionar durante una prueba unitaria?
victor
5
Sería útil para mí y para otros si mostrara algunas muestras en lugar de hacer críticas.
aog
Está bien para sitios web pequeños.
alikuli
-7

¡He hecho que me duela la cabeza por nada! La respuesta fue muy simple: simplemente volví a lo básico ...

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

agregue esta línea a continuación después de actualizar / eliminar: está volviendo a cargar su entidad, sin métodos de sistema sofisticados.

e2 = new some_Entities(); //reset.
buffy555
fuente
2
Eso "funcionará", es simplemente una idea terrible y tendrá otras consecuencias
Adam Hey