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!

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


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

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/


¡¡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.


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


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

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
}

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.

2
Eso "funcionará", es simplemente una idea terrible y tendrá otras consecuencias
Adam Hey
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.