Контекст оновлення Entity Framework?


100

Як я міг оновити свій контекст? У мене є об'єкти, засновані на переглядах з моєї бази даних, і коли я здійснив оновлення на одній суті, яка має властивості навігації до представлень, сутність оновлюється, але вигляд не оновлюється відповідно до нових оновлень ... просто хочу знову отримати Db дані. Дякую!

Відповіді:


91

Найкращий спосіб оновити сутність у вашому контексті - розпоряджатися своїм контекстом та створювати новий.

Якщо вам дійсно потрібно оновити якусь сутність, і ви використовуєте підхід 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; }
Jinjinov

У EF Ядра ви можете використовувати Query () Load () так, наприклад.context.Entry(order).Collection(o => o.NavigationProperty).Query().Load();
Rubenisme

Я не розумію, чому за це рішення голосують так високо. контекст. Вступ (сутність) .Колекція <TElement> (навігаційна властивість) .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();
     }
}

Якщо ви використовуєте entitFramework 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);
}

Найкраща порада в будь-якому випадку, спробуйте використовувати "короткочасний контекст", і ви уникнете подібних проблем.

Я написав пару статей з цього приводу:

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


хороший!! Врятував мій день!
Раду Д

15

Використовуйте метод Refresh :

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();?
Csaba Toth

Наскільки я пам'ятаю, .Reload()вона недоступна в EF6. @CsabaToth
Рахман

0

Оновлення контексту db з Reload не рекомендується шляхом через втрату продуктивності. Це достатньо хороша і найкраща практика ініціалізувати новий екземпляр dbcontext перед кожною операцією. Він також надає вам оновлений контекст для кожної операції.

using (YourContext ctx = new YourContext())
{
   //Your operations
}

6
Чувак .. Демпінг вашого контексту щоразу також оновлюватиме речі, які ви не хочете, буде оновлено, що справді призведе до проблем із продуктивністю.
LuckyLikey

2
Це жахлива ідея, оскільки вона впливає на можливість писати одиничні тести. Якщо ваш код вимикається і з’являється новий контекст, як це буде працювати під час одиничного тесту?
переможець

5
Було б корисно і мені, і іншим, якщо ви покажете деякі зразки, а не критикуєте.
серпня 1717

Його штраф для невеликих веб-сайтів.
алікули

-7

Я зробив власну голову боляче через нічого! Відповідь була дуже проста - я просто повернувся до основ ...

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

додайте цей рядок нижче після оновлення / видалення - ви повторно завантажуєте не потрібні системні методи.

e2 = new some_Entities(); //reset.

2
Це "спрацює" - це просто жахлива ідея і матиме інші наслідки
Адам Ей,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.