Entity Framework Обновить контекст?

101

Как я могу обновить свой контекст? У меня есть сущности, основанные на представлениях из моей базы данных, и когда я сделал обновление для одной таблицы Entity, у которой есть свойства навигации для представлений, объект обновляется, но представление не обновляется в соответствии с новыми обновлениями ... просто хочу получить снова из Дб данных. Спасибо!

user2528557
источник

Ответы:

92

Лучший способ обновить сущности в вашем контексте - удалить ваш контекст и создать новый.

Если вам действительно нужно обновить какой-либо объект, и вы используете подход Code First с классом DbContext, вы можете использовать

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

Чтобы перезагрузить свойства навигации коллекции, вы можете использовать

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

Ссылка: https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbentityentry.reload(v=vs.113).aspx#M:System.Data.Entity.Infrastructure.DbEntityEntry .Перезагрузить

RX_DID_RX
источник
3
Я не могу заставить это работать, чтобы перезагрузить дочерние свойства навигации.
Пол
@David, ты можешь использовать, context.ReloadNavigationProperty(parent, p => p.Children);если у тебя естьclass Parent { ICollection<Child> Children; }
Джинджинов
В EF Ядра вы можете использовать Query () Load () так, например.context.Entry(order).Collection(o => o.NavigationProperty).Query().Load();
Rubenisme
Я не понимаю, почему это решение так высоко оценено. context.Entry (entity) .Collection <TElement> (navigationProperty) .Query () не перезагружает дочернюю коллекцию. Он дает вам только Iqueryable, представляющий запрос, используемый для получения коллекции. Буквально ничего не делает.
statler
72
yourContext.Entry(yourEntity).Reload();
kravits88
источник
3
Спасибо за простое решение. Я не вижу необходимости инкапсулировать это в метод расширения, такой как RX_DID_RX,
Томас
Это было для меня спасением. Спасибо!
Кевин
19
Обратите внимание, что это не перезагружает свойства навигации коллекции, а только саму запись объекта.
Джеймс Уилкинс
28

Если вы хотите перезагрузить определенные сущности с помощью DbContextApi, RX_DID_RX уже дал вам ответ.

Если вы хотите перезагрузить / обновить все загруженные вами объекты:

Если вы используете Entity Framework 4.1+ (возможно, EF5 или EF 6), API DbContext:

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

Если вы используете entityFramework 4 (ObjectContext API):

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

В любом случае лучший совет - постарайтесь использовать «кратковременный контекст», и вы избежите подобных проблем.

Я написал пару статей по этому поводу:

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

Кристиан Родригес
источник
хороший!! Спас мой день!
Radu D
15

Используйте метод обновления :

context.Refresh(RefreshMode.StoreWins, yourEntity);

или, в качестве альтернативы, избавьтесь от текущего контекста и создайте новый.

Альберто
источник
@JMK Что именно здесь не работает? У меня вроде нормально работает (EF 6.1.1).
Себастьян Крысмански
@SebastianKrysmanski Я прокомментировал это почти год назад, может быть, с тех пор это исправили?
JMK
5
Я думаю, что это работает только для objectcontext, но не для dbcontext. Между ними необходим разговор
batmaci
3
@batmaci Что легко сделать с помощью((IObjectContextAdapter)dbContext).ObjectContext
Daniel Z.
3
Который не был заявлен так немного неполно.
user441521
6

context.Reload () не работал у меня в MVC 4, EF 5, поэтому я сделал это.

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

и он работает нормально.

Чаудхари Калим Ахмад
источник
1

EF 6

В моем сценарии Entity Framework не собирала недавно обновленные данные. Причина может быть в том, что данные были обновлены за пределами его области. Обновление данных после получения разрешило мою проблему.

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
Я с EF6. Почему это лучше, чем _context.Entry(entity).Reload();?
Чаба Тот,
Насколько я помню, .Reload()в EF6 нет. @CsabaToth
Махбубур Рахман,
0

Обновление контекста базы данных с помощью Reload не рекомендуется из-за потери производительности. Достаточно хорошо и лучше всего инициализировать новый экземпляр dbcontext перед выполнением каждой операции. Он также предоставляет вам обновленный контекст для каждой операции.

using (YourContext ctx = new YourContext())
{
   //Your operations
}
Aog
источник
6
Чувак ... Каждый раз сбрасывая ваш контекст, вы также обновите то, что вам не нужно, что действительно приведет к проблемам с производительностью.
LuckyLikey
3
Это ужасная идея, поскольку она влияет на возможность написания модульных тестов. Если ваш код отключается и открывает новый контекст, как это будет работать во время модульного тестирования?
victor
5
Для меня и других было бы полезно, если бы вы показали некоторые образцы, а не критиковали.
aog
Это нормально для небольших сайтов.
аликули
-1

На самом деле я предлагаю удалить всю сущность и воссоздать ее в зависимости от вашего подхода.

Баян Ал_А6рш
источник
-7

Я из-за ничего не разболел себе голову! Ответ был очень прост - я просто вернулся к основам ...

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

добавьте эту строку ниже после обновления / удаления - вы повторно загружаете свою сущность - нет причудливых системных методов.

e2 = new some_Entities(); //reset.
баффи555
источник
3
Это «сработает» - это просто ужасная идея и будет иметь другие последствия
Адам Хей