Необходимо обновить sh объект Db, который был обновлен в другой области - PullRequest
1 голос
/ 09 марта 2020

У меня есть бэкэнд-сервис, который имеет собственный контекст. Эта служба опрашивает внешние устройства каждую минуту и ​​запускается по минутному таймеру, чтобы повторить процесс. Каждую минуту служба также проверяет изменения состояния устройства (запуск, остановка, запуск, выключение), которые необходимо применить. Эти изменения состояния, если таковые имеются, будут исходить от метода Post сервера Razor Page, использующего DBcontext и DI для обновления DeployedAppliance в БД.

Проблема заключается в следующем: страница Razor успешно обновляет базу данных DeployedAppliance (перечисление состояния). Однако область обслуживания бэкэнда, создаваемая заново каждую минуту, не получает новое состояние DeployedAppliance.

Вот некоторый соответствующий код бэкэнда:

    public class ApplianceService : IHostedService, IDisposable
    {
        private Timer _timer;
        private readonly IServiceScopeFactory _serviceScopeFactory;
        private IApplianceManager applianceMgr;

        public Task StartAsync(CancellationToken stoppingToken)
        {
            applianceMgr = new ApplianceManagerImpl();
            ... 
           _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));
        }

        private void DoWork(object state)
        {
            // Create local scope. 
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                var _db = scope.ServiceProvider.GetRequiredService<DbContext>();
                applianceMgr.Db = _db;
                applianceMgr.DoRemoteAppliancePolling();
                applianceMgr.CheckForApplianceStateChange();
            }
         }        
     }

     public class ApplianceManager : IApplianceManager 
     {   
        DeployedAppliance DeployedAppliance {get; set;}

        ...
        public void CheckForApplianceStateChange()      
        {
            // This DeployedAppliance object never gets the change in state that is actually in the Db
            DeployedAppliance = Db.DeployedAppliances.Find(ApplianceDeploymentID);
            ...
        }
     }

Я посмотрел на представления stackoverflow для refre sh ДБ сущностей. Я попытался следующий код, чтобы refre sh Db.

// refresh DBcontext
var context = ((IObjectContextAdapter)Db).ObjectContext;
var refreshableObjects = Db.ChangeTracker.Entries().Select(c => c.Entity).ToList();
context.Refresh(RefreshMode.StoreWins, refreshableObjects);

Как бы то ни было, этот код выдает: InvalidCastException: Невозможно привести объект типа 'Pilot.Models.Database.DbContext' к типу 'System .Data.Entity.Infrastructure.IObjectContextAdapter. Обратите внимание, что DbContext наследуется от IdentityDbContext.

1 Ответ

0 голосов
/ 09 марта 2020

Вы можете сделать следующее:

  1. Получить список added/modified сущностей
  2. Выполнить SaveChanges()
  3. Отсоединить added/modified сущностей от вашего context.

Вот пример, чтобы сделать это, используя ObjectContext:

IEnumerable<object> entitiesCollection = from e in objectContext.ObjectStateManager.GetObjectStateEntries
                                 (EntityState.Added | EntityState.Modified)
                                      select e.Entity;

objectContext.SaveChanges();

foreach (object entity in entitiesCollection)
{
    if (entity!= null)
    {
        objectContext.Detach(entity);
    }
}

Таким образом, поскольку добавленные / измененные сущности отделены от вашего контекста, EntityFramework придется перезагрузить их из базы данных, чтобы вы получили новые обновленные значения.

РЕДАКТИРОВАТЬ:

Что касается вашего комментария о том, как сделать это в EF Core :

Как ajcvickers опубликовано здесь 17 апреля 2018 г .:

В EF Core в настоящее время нет эквивалента. context.Entry(foo).Reload() на данный момент самая близкая вещь, но она работает только на одной сущности. В общем, мы рекомендуем использовать кратковременные контексты, которые охватывают одну единицу работы. Обычно это делает ненужной перезагрузку из магазина.

Кроме того, как сообщается здесь тем же лицом 15 июля 2019 года, разработка этой функции была добавлена ​​в бэклог EF Product. :

Помещение в очередь для рассмотрения поведения DbContext в EF Core, аналогичного ObjectContext.Refre sh в старом стеке.

...