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


101

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

Ответы:


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 .Перезагрузить


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

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
}

6
Чувак ... Каждый раз сбрасывая ваш контекст, вы также обновите то, что вам не нужно, что действительно приведет к проблемам с производительностью.
LuckyLikey

3
Это ужасная идея, поскольку она влияет на возможность написания модульных тестов. Если ваш код отключается и открывает новый контекст, как это будет работать во время модульного тестирования?
victor

5
Для меня и других было бы полезно, если бы вы показали некоторые образцы, а не критиковали.
aog

Это нормально для небольших сайтов.
аликули

-1

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


-7

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

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

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

e2 = new some_Entities(); //reset.

3
Это «сработает» - это просто ужасная идея и будет иметь другие последствия
Адам Хей
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.