如何刷新 Entity Framework Core DBContext? [英] How to refresh an Entity Framework Core DBContext?

查看:52
本文介绍了如何刷新 Entity Framework Core DBContext?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我的表被另一方更新时,dotnet core 中的 db 上下文仍然返回旧值,如何强制刷新 db 上下文?

When my table is updated by another party, the db context in dotnet core still return the old value, how can I force the Db context to refresh?

我已经做过研究,但我只发现人们使用 Reload 方法来强制刷新上下文,这在 EF 核心中不可用.

I've done research but I only found people use Reload method, which is not available in EF core, to force the context to refresh.

其他一些解决方案建议在使用后处理上下文,但我收到错误消息,说数据库上下文是由依赖注入创建的,我不应该弄乱它.

Some other solution suggests dispose the context after using, but I get error saying the DB context is created by dependency injection and I should not mess up with it.

推荐答案

Dependency Injection and DbContext

您提到当您尝试重新创建您的 DbContext 时,您会收到一个关于由您的依赖注入 (DI) 系统管理的上下文的错误.使用依赖注入系统创建对象有两种不同的风格.DI 可以创建一个全局单例实例,作为服务在所有消费者之间共享,也可以为每个工作范围/工作单元(例如,Web 服务器中的每个请求)创建一个实例.

Dependency Injection and DbContext

You mention that when you try to recreate your DbContext, you get an error about the context being managed by your dependency injection (DI) system. There are two different styles of using a dependency injection system for object creation. The DI can either create a global singleton instance that is shared as a service between all consumers or it can create an instance per scope/unit of work (e.g., per request in a web server).

如果您的 DI 系统配置为创建 DbContext 的单个全局共享实例,那么您将遇到与长期存在的 DbContext 相关的各种问题.

If your DI system is configured to create a single global shared instance of DbContext, then you will encounter various problems associated with long-lived DbContext.

  • DbContext 按照设计,永远不会从其缓存中自动删除对象,因为它不是为长期存在而设计的.因此,长期存在的 DbContext 将浪费地保留内存.
  • 如果不手动重新加载它加载的每个实体,您的代码将永远不会看到加载到其缓存中的项目的更改.
  • DbContext 只允许在任何时候运行一个查询并且不是线程安全的.如果您尝试在全局共享实例上运行多个查询,它会抛出 DbConcurrencyException(在至少在它的异步接口上,不确定它的同步接口).
  • DbContext, by design, never automatically removes objects from its cache because it is not designed to be long-lived. Thus, a long-lived DbContext will retain memory wastefully.
  • Your code will never see changes to items loaded into its cache without manually reloading each entity it loads.
  • DbContext only allows one query to run at any time and is not threadsafe. If you try to run multiple queries on a globally shared instance, it will throw DbConcurrencyException (at least on its async interface, not sure about its sync interface).

因此,最佳做法是为每个工作单元使用一个 DbContext.您的 DI 系统可以通过配置为您的应用程序在一个范围内处理的每个请求提供一个新实例来帮助您解决这个问题.例如,ASP.NET Core 的依赖注入系统支持按请求对实例进行作用域划分.

Thus, the best practice is to use a single DbContext per unit of work. Your DI system can help you with this by being configured to provide a fresh instance for each request your application processes within a scope. For example, ASP.NET Core’s Dependency Injection system supports scoping instances by request.

获取新数据的最简单方法是创建一个新的 DbContext.但是,在您的工作单元内,或在您的 DI 系统提供的范围粒度的约束内,您可能会触发一个外部流程,该流程应该直接在数据库中修改您的实体.在退出 DI 的范围或完成工作单元之前,您可能需要看到该更改.在这种情况下,您可以通过分离数据对象的实例来强制重新加载.

The easiest way to get fresh data is to create a new DbContext. However, within your unit of work, or within the constraints of the granularity of scoping provided by your DI system, you may trigger an external process which is supposed to modify your entity directly in the database. You may need to see that change before exiting your DI’s scope or completing your unit of work. In that case, you can force a reload by detaching your instance of the data object.

为此,首先获取EntityEntry<> 用于您的对象.这是一个对象,它允许您为该对象操作 DbContext 的内部缓存.然后,您可以通过将 EntitytState.Detached 分配给其 State 属性来将此条目标记为分离.我相信这会将条目留在缓存中,但会导致 DbContext 在您将来实际加载条目时删除并替换它.重要的是它会导致未来加载将新加载的实体实例返回到您的代码.例如:

To do this, first get the EntityEntry<> for your object. This is an object which lets you manipulate DbContext’s internal cache for that object. You can then mark this entry detached by assigning EntitytState.Detached to its State property. I believe that this leaves the entry in the cache but causes the DbContext to remove and replace it when you actually load the entry in the future. What matters is that it causes a future load to return a freshly loaded entity instance to your code. For example:

var thing = context.Things.Find(id);
if (thing.ShouldBeSentToService) {
    TriggerExternalServiceAndWait(id);

    // Detach the object to remove it from context’s cache.
    context.Entities(thing).State = EntityState.Detached;

    // Then load it. We will get a new object with data
    // freshly loaded from the database.
    thing = context.Things.Find(id);
}
UseSomeOtherData(thing.DataWhichWasUpdated);

这篇关于如何刷新 Entity Framework Core DBContext?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆