EF Core DbContext 缓存结果包括具有动态全局过滤器的实体

问题描述 投票:0回答:1

我在使用名为

RegistrationRoundId
的基于环境的属性时遇到 EF Core DbContext 问题,该属性可以在环境上下文中由
RegistrationRoundIdProvider
更改。
RegistrationRoundId
用于 DbContext 的全局查询过滤器,当我请求一个嵌套对象依赖于
RegistrationRoundId
的查询,然后使用
RegistrationRoundId
提供程序更改环境
RegistrationRound
并请求相同的查询时,结果嵌套实体似乎被缓存并与依赖于新
RegistrationRoundId
值的新实体相关联。我尝试将
RegistrationRoundId
声明为 DbContext 的属性并遵循 EF Core 约定,但问题仍然存在。但是,我注意到问题在两种情况下消失了:当我使用 AsNoTracking() 扩展方法时,当我在两个不同的范围内请求两个查询时,我假设这会导致在每个范围内创建一个新的 DbContext 实例。有人可以解释为什么会出现这个问题以及如何解决这个问题吗? 我想知道是否有专业的建议而不是手动和重复的解决方法

这是我的代码片段,显示了问题

 // here the parent context of the registration round id, says id1
      r = lst.Select(e => (object)new
    {
        e.Id,
        e.StudyYearId,
        countRequest = e.Requests.Count,
        // requests related to id1 will be present alone here
        requests = e.Requests.Select(e => e.RegistrationRoundId).ToList()
    })
        .FirstOrDefault();
// says id2
using (_currentRegistrationRound.Change(rs[1].Id))
        {

            r1 = (await qryM.ToListAsync())
        .Select(e => (object)new
        {
            e.Id,
            e.StudyYearId,
            countRequest = e.Requests.Count,
             //here the requests are related to id1 and id2
            requests = e.Requests.Select(e => e.RegistrationRoundId).ToList()
        })
        .FirstOrDefault();



        }
        // says id3
        using (_currentRegistrationRound.Change(Guid.NewGuid()))
        {

            r2 = (await qryM.ToListAsync())
      .Select(e => (object)new
      {
          e.Id,
          e.StudyYearId,
          countRequest = e.Requests.Count,
          // here the id3 has no related requests, however, id1 and id2 related requests 
          //are present !!
          requests = e.Requests.Select(e => e.RegistrationRoundId).ToList()
      })
      .FirstOrDefault();

更新

我在 DdContext 中使用了一个简单的依赖属性:

public Guid RegistrationRoundId {get; set;}
并用于检查不幸显示相同错误结果的行为

见下图:

c# entity-framework asp.net-core entity-framework-core
1个回答
0
投票

但是,我注意到问题在两种情况下消失了:当我使用

AsNoTracking()
扩展方法时,当我在两个不同的范围内请求两个查询时,我假设这会导致
DbContext
的新实例被创建每个范围。有人可以解释为什么会出现这个问题以及如何解决这个问题吗?

好了,你看到了问题的原因——跟踪查询.

当您使用跟踪查询和生成的物化实体实例(由于

ToList{Async}
调用)时,即使在数据库查询上应用了全局查询过滤器,结果也会合并到缓存的实体实例中(客户端获胜),而不是替换它们。也没有过滤应用于已经加载的实体。所有这一切都是由于 EF Core 导航修复,并且不要忘记我们可以手动将实例添加到这些跟踪的集合中,同样,不会应用过滤。

查看 Filtered include 文档中的以下段落,因为这两个功能使用同一个过滤子系统(全局查询过滤器只是自动添加过滤器,而在过滤包含中它们是手动指定的):

注意

在跟踪查询的情况下,由于导航修复,Filtered Include 的结果可能出乎意料。之前查询过并存储在 Change Tracker 中的所有相关实体都将出现在 Filtered Include 查询的结果中,即使它们不符合过滤器的要求。在这些情况下使用过滤包含时,请考虑使用

NoTracking
查询或重新创建
DbContext

至于解决方案,如您所见,文档建议使用

NoTracking
查询,因此要么像您已经做的那样添加
AsNoTracking()
,要么使用投影 (
Select
) 查询(直接在 LINQ to Entities 查询源上,无需中间
ToList{Async}
和类似),这是您获得所需确切数据的唯一方法。没有涉及 EF Core 跟踪的解决方案,因为该行为是“设计使然”的,而不是错误,并且不太可能更改。

© www.soinside.com 2019 - 2024. All rights reserved.