C# 需要刷新已在另一个作用域中更新的Db实体

C# 需要刷新已在另一个作用域中更新的Db实体,c#,asp.net,scope,entity-framework-6,C#,Asp.net,Scope,Entity Framework 6,我有一个后端服务,它有自己的作用域上下文。此服务每分钟轮询一次外部设备,并在一分钟计时器上运行以重复此过程。每分钟,该服务还检查需要应用的设备状态更改(启动、停止、运行、关闭)。这些状态更改(如果有)将来自Razor页面服务器Post方法,该方法使用DBcontext和DI更新数据库中的DeployedApplication 问题如下:Razor页面成功更新了DeployedApplication DB(状态枚举)。但是,每分钟重新创建一次的后端服务范围并没有获得新的DeployedApplic

我有一个后端服务,它有自己的作用域上下文。此服务每分钟轮询一次外部设备,并在一分钟计时器上运行以重复此过程。每分钟,该服务还检查需要应用的设备状态更改(启动、停止、运行、关闭)。这些状态更改(如果有)将来自Razor页面服务器Post方法,该方法使用DBcontext和DI更新数据库中的DeployedApplication

问题如下:Razor页面成功更新了DeployedApplication DB(状态枚举)。但是,每分钟重新创建一次的后端服务范围并没有获得新的DeployedApplication状态

以下是一些相关的后端代码:

    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);
            ...
        }
     }
然而,这段代码抛出:
InvalidCastException:无法将“Pilot.Models.Database.DbContext”类型的对象强制转换为“System.Data.Entity.Infrastructure.IOObjectContextAdapter”类型。请注意,DbContext继承自IdentityDbContext。

您可以执行以下操作:

  • 获取添加/修改的
    实体列表
  • 执行
    SaveChanges()
  • 从上下文中分离添加/修改的
    实体
  • 下面是一个使用
    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);
        }
    }
    
    IEnumerable entitiesCollection=来自objectContext.ObjectStateManager.GetObjectStateEntries中的e
    (EntityState.Added | EntityState.Modified)
    选择e.实体;
    objectContext.SaveChanges();
    foreach(EntityCollection中的对象实体)
    {
    如果(实体!=null)
    {
    分离(实体);
    }
    }
    
    这样,由于添加/修改的实体与上下文分离,
    EntityFramework
    必须从数据库中重新加载它们,以便获得新的更新值

    编辑:

    关于您对如何在EF Core中执行此操作的评论:

    如2018年4月17日发布的:

    目前EF Core中还没有一个等价物。
    context.Entry(foo.Reload()
    是当前最接近的东西,但是 仅适用于单个实体。 一般来说,我们建议使用涵盖 单一工作单元。这通常会导致从商店重新加载 不必要

    此外,正如同一人在2019年7月15日发布的,该功能的开发已添加到EF产品待办事项中:

    将此放到待定日志中考虑EF中的DbCurror行为 核心类似于ObjectContext。在旧堆栈中刷新


    您可以执行以下操作:

  • 获取添加/修改的
    实体列表
  • 执行
    SaveChanges()
  • 从上下文中分离添加/修改的
    实体
  • 下面是一个使用
    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);
        }
    }
    
    IEnumerable entitiesCollection=来自objectContext.ObjectStateManager.GetObjectStateEntries中的e
    (EntityState.Added | EntityState.Modified)
    选择e.实体;
    objectContext.SaveChanges();
    foreach(EntityCollection中的对象实体)
    {
    如果(实体!=null)
    {
    分离(实体);
    }
    }
    
    这样,由于添加/修改的实体与上下文分离,
    EntityFramework
    必须从数据库中重新加载它们,以便获得新的更新值

    编辑:

    关于您对如何在EF Core中执行此操作的评论:

    如2018年4月17日发布的:

    目前EF Core中还没有一个等价物。
    context.Entry(foo.Reload()
    是当前最接近的东西,但是 仅适用于单个实体。 一般来说,我们建议使用涵盖 单一工作单元。这通常会导致从商店重新加载 不必要

    此外,正如同一人在2019年7月15日发布的,该功能的开发已添加到EF产品待办事项中:

    将此放到待定日志中考虑EF中的DbCurror行为 核心类似于ObjectContext。在旧堆栈中刷新


    我已经尝试了这段代码来获取ObjectContext,但是,它不适用于IdentityDbContext:ObjectContext ObjectContext=((IOObjectContextAdapter)_db);它引发运行时异常以下是异常详细信息:无法将类型为“BMS_Pilot.Models.Database.BMSDbContext”的对象强制转换为类型为“System.Data.Entity.Infrastructure.IObjectContextAdapter”的对象如何专门使用EntityFrameworkCore进行这种类型的实体操作?@TommyBoyWest您可能会发现如何获取使用DbContext修改了实体。@TommyBoyWest此链接对于使用DbContext进行分离也很有用:我已尝试使用此代码获取ObjectContext,但是,它不适用于IdentityDbContext:ObjectContext ObjectContext=((IObjectContextAdapter)_db).ObjectContext;它引发运行时异常以下是异常详细信息:无法将“BMS_Pilot.Models.Database.BMSDbContext”类型的对象强制转换为“System.Data.Entity.Infrastructure.IObjectContextAdapter”类型,您可能会发现如何专门使用EntityFrameworkCore进行这种类型的实体操作?@TommyBoyWest要使用DbContext获取已修改实体的列表。@TommyBoyWest此链接对于使用DbContext进行分离也很有用: