实体框架中的缓存如何工作?

2023-12-09

我看到大量关于人们努力让 EF 不发送缓存数据的帖子。我坐在这里想知道他们如何让它发送缓存数据......

详细信息如下: 使用 Entity Framework Core 6.0.6 的 .NET 6.0 上的 ASP.NET Core 最新版本。 通过 Swagger 站点页面测试控制器方法。 DbContext 具有作用域并注入依赖项。 未使用 AsNoTracking。

该方法非常简单_DbContext.Set.ToListAsync()。

  1. 我称该方法为。
  2. 直接更新数据库中先前从该方法返回的记录之一的值(通过 Sql Management Studio,而不是同一服务)。
  3. 再次调用该方法。

我希望第二次调用具有“陈旧”数据,即与第一次调用相同的数据。但是,它有我从数据库中更新的数据!?第二次调用要快得多,我认为这是因为 EF 缓存了我的查询和元数据,但它似乎没有缓存查询的实际结果。

根据我的测试,它看起来只会缓存同一请求中的结果。一旦请求完成,DbContext 就会被释放,然后结果缓存就会消失。正确的?因此,如果我想在不同的 Web 请求之间保留结果缓存,那么我必须通过 NCache、其他一些包或自己编写代码来实现自己的缓存?


实体框架依赖于跟踪机制(请参阅this and this)。它本身不是缓存,但它可以产生类似的效果,尽管主要目标之一是跟踪更改,以便将它们传播到数据库。

更改跟踪“绑定”到上下文的具体实例(即不在不同实例/全局之间共享)。变更跟踪的重要功能之一是身份解析:

由于跟踪查询使用更改跟踪器,因此 EF Core 将在跟踪查询中进行身份解析。当具体化实体时,EF Core 将从更改跟踪器返回相同的实体实例(如果已被跟踪)。如果结果多次包含相同的实体,则每次出现都会返回相同的实例。无跟踪查询不使用更改跟踪器,也不进行身份解析。因此,即使结果中多次包含同一实体,您也会返回实体的新实例。

如果数据库在同一上下文中的请求之间“外部”更新,这可能会导致数据过时:

using (var ctx1 = new AppContext())
{
    var entity = await ctx1.SomeEntity
        .Where(e => e.Id == 1)
        .FirstOrDefaultAsync();

    using (var ctx2 = new AppContext())
    {
        var theSameEntity = await ctx2.SomeEntity
            .Where(e => e.Id == 1)
            .FirstOrDefaultAsync();
        theSameEntity.SomeTextField = "Updated"; // assuming it had another value
        await ctx2.SaveChangesAsync();
    }

    var entity1 = await ctx1.SomeEntity
        .Where(e => e.Id == 1)
        .FirstOrDefaultAsync()
    var referenceEquals = object.ReferenceEquals(entity, entity1); // True
    var field = entity1.SomeTextField; // field will have the original value, not "Updated"
}

第二次调用要快得多,我相信这是因为 EF 缓存了我的查询和元数据

其潜在原因有多种:

  • 如果第一个查询是在此应用程序运行中第一次执行此查询,则 EF Core 可以缓存查询翻译结果,以便在后续查询(跨上下文实例)中重用。此外,如果实体已被跟踪,则 EF 的当前迭代将不会重新创建和重新映射获取的数据。不确定我是否记得正确,但如果已请求已跟踪的实体,EF/EF Core 的先前迭代可能会完全跳过查询数据库,但我在这里可能是错的。

还有几个因素影响“启动时间”,即在计算机上执行第一个操作的时间DbContext当那个时候DbContexttype 在应用程序中首次使用。

  • Model initialization - see the compiled models section of the docs:

    创建一个DbContext实例不会导致 EF 模型初始化,导致模型初始化的典型第一个操作包括调用DbContext.Add或执行第一个查询。

  • 连接管理 - EF Core 将需要建立与数据库服务器的连接,然后将其汇集并重用(更多一点 -here),在某些情况下可能会花费相当长的时间,这将不适用于后续查询(如果底层物理连接池有足够的可用连接)。
  • 即时编译- 第一次调用某个方法时,运行时需要编译它,在使用 EF Core 的上下文中它应该可以忽略不计(尽管理论上与EF Core 编译模型)但仍然值得一提(显然适用于第一次调用某些特定方法)。

但它似乎没有缓存查询的实际结果。

它同时是部分正确和部分错误的。如前所示 - 如果数据实际上已更改,EF 将不会更新跟踪的实体。但如果数据被删除,EF 会发现:

using (var ctx1 = new AppContext())
{
    var entity = await ctx1.SomeEntity
        .Where(e => e.Id == 1)
        .FirstOrDefaultAsync();

    using (var ctx2 = new AppContext())
    {
        var theSameEntity = await ctx2.SomeEntity
            .Where(e => e.Id == 1)
            .FirstOrDefaultAsync();
        ctx2.DeliveryComment.Remove(theSameEntity); // remove
        await ctx2.SaveChangesAsync();
    }

    var entity1 = await ctx1.SomeEntity
        .Where(e => e.Id == 1)
        .FirstOrDefaultAsync()
    var isNull = entity1 == null; // True
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实体框架中的缓存如何工作? 的相关文章

随机推荐

  • 使用 ggplot aes_string、group 和 linetype 时出现的问题

    假设我有这个数据集 x lt rnorm 1000 y lt rnorm 1000 2 5 line color lt sample rep 1 4 250 line type lt as factor sample rep 1 5 200
  • Android:如何使用计时器

    这是我的第一篇文章 所以我正在学习 Android 和 Java 来自 Actionscript 并且我正在开发一个项目 我试图单击一个 ImageView 让该 ImageView 交换图像一秒钟 然后返回到原始图像 这是一个点击游戏 听
  • HashMap 中的重复值

    我遇到了大麻烦 创建了一个 hashMap 并使用相同的键插入了两个值 StringBuilder作为map的键 现在 虽然尝试使用 StringBuilder 对象检索数据工作正常 但在其他情况下它无法返回任何值 我在下面给出的代码中列出
  • 为什么我无法使用 Type.GetType() 来查找 app.config 中引用的插件实例的类型?

    所以这就是交易 我有我的解决方案 其中有几个项目 包装器项目 这只是一个控制台应用程序 当前在调试期间代表 Windows 服务 一个工作者项目 包含代码的核心内容 这样我就可以轻松地调试 Windows 服务的代码 而不用头疼 插件库项目
  • 在 JS 中将月份名称转换为月份编号的最简单方法? (一月 = 01)

    只是想隐蔽Jan to 01 日期格式 我可以用array 但正在寻找另一种方式 有什么建议吗 只是为了好玩我这样做了 function getMonthFromString mon return new Date Date parse m
  • 使用 Windows DOM 和 TXMLDocument 验证 XML:在某些计算机上不起作用

    我有一些 Delphi 代码来读取和验证基于 XSD 文档的 XML 文件 我正在使用 Windows DOM TMXLDocument 本文解释了底层逻辑 它适用于某些计算机 即引发违规标签的异常 但在较新的计算机上 它不会引发任何异常
  • 如何以编程方式将搜索栏添加到 UITableView 标头?

    我将如何以编程方式将搜索栏添加到 uitableview 标头中 具体来说 我有一个栏按钮项目 当按下它时 我想在搜索栏中以动画方式进入表视图标题 当按下取消按钮时 它将以动画方式退出视图 并且标题缩放回正常状态 这可能吗 谢谢 它基于Sw
  • 如何在没有装饰器语法的情况下编写 Angular2?

    我大致如下JavaScript 打字稿快速入门Angular2编写我的应用程序ES6但无法让装饰器工作 entry js import as stylesheet from assets styles app scss import jQu
  • 您可以使用 Subversion 进行部分结账吗?

    如果我在 trunk 下有 20 个目录 每个目录中有很多文件 并且只需要其中的 3 个目录 是否可以仅使用 trunk 下的这 3 个目录进行 Subversion 签出 事实上 由于对我的帖子的评论 它看起来像稀疏目录是要走的路 我相信
  • jetty webSocket:java.lang.IllegalStateException:已提交

    我在我的 Web 应用程序中使用 Jetty Websockets 当我尝试重定向到注销 jsp 时 出现此错误 oejs ServletHandler test java lang IllegalStateException Commit
  • 在 directshow 中以编程方式更改录制文件

    我使用 directshow 制作了一个控制台应用程序 它从实时源 现在是网络摄像头 然后是电视捕获卡 进行记录 在叠加中添加当前日期和时间 然后将音频和视频保存为 asf 现在我希望输出文件每 60 分钟更改一次而不停止图表 我不能错过直
  • 多核处理器的多线程

    我有三星 Galaxy S3 它使用自己的 Exynos 4 四核处理器 所以我想优化我的应用程序 使其可以使用所有 4 个处理器核心 所以我做了一些测试 在一个线程中运行任务 处理时间 8 秒 在四个线程中运行任务 处理时间 仍为 8 秒
  • 如何在Lua中获取表的“sizeof”?

    我正在使用 Lua 涉足 Love2D 并且刚刚实现了一个 StateMachine 来处理一组状态之间的转换 例如IntroState MenuState PlayState 等 在以前的程序中 我通常释放只是 一次性交易 的对象和 或状
  • 如何添加注释以从 jacoco 代码覆盖率报告中排除方法?

    我有一些 Java 代码 我想将其从代码覆盖率中排除 我该怎么做 我希望能够添加注释 有没有办法配置或扩展 jacoco 如 gradle 中使用的 来使用它 Example public class Something ExcludeFr
  • python 有排序列表吗?

    我的意思是一个结构 O log n 复杂度x push 运营 查找元素的复杂度为 O log n 计算复杂度为 O n list x 将被排序 我还有一个关于性能的相关问题list insert 现在是here 您的大 O 要求有什么特殊原
  • Python Unittest:打开并等待程序关闭

    目前 我尝试创建一个打开文件 使用相应的应用程序 的单元测试 然后测试运行应该等到程序关闭 def test HFG self print please edit this file os chdir r C test a os start
  • Excel VBA 比较列数据复制行

    好吧 在这里许多编码专家的帮助下 我设法以某种方式编写了这段代码 我需要创建一个宏来比较两个工作表中的数据 在我的两个工作表中 都有一个名为 eRequest ID 的列 我必须复制以下记录行 DO NOT有一个 eRequest ID 两
  • Magento 免费送货和优惠券折扣

    我有一个免费送货价格规则 其配置如下 所有客户群体 无优惠券 每个客户的使用次数 0 条件 购物车总数 gt 100 发货国家 地区 NL 或 BE 或 DE 免费送货 与配套商品一起发货 然而 当我输入具有固定折扣金额的优惠券时 免费送货
  • RestTemplate + ConnectionPoolTimeoutException:等待来自池的连接超时

    当应用程序没有任何负载时 我在生产中突然遇到此错误 当我的代码尝试使用 Spring Rest 模板发送 PUT 消息时出现问题 这是我如何初始化restTemplate的代码 private static final RestTempla
  • 实体框架中的缓存如何工作?

    我看到大量关于人们努力让 EF 不发送缓存数据的帖子 我坐在这里想知道他们如何让它发送缓存数据 详细信息如下 使用 Entity Framework Core 6 0 6 的 NET 6 0 上的 ASP NET Core 最新版本 通过