过滤包含 AsNoTracking 时的奇怪行为
Strange behaviour when filtering on Include with AsNoTracking
不知道是不是应该这样,但是我觉得很奇怪,因为更改了查询结果。
当我执行下面的查询时,我得到的实体只有 2 个“Mensagens”实体,因为我只过滤活动,所以它是正确的,我的数据库中有 2 个活动实体和 1 个非活动实体。
return await context.Lancamentos
.Include(x => x.UsuarioCriacao)
.Include(x => x.Mensagens.Where(m => m.Ativo))
.ThenInclude(m => m.MensagemMedias)
.ThenInclude(m => m.MediaWhatsapp)
.ThenInclude(m => m.TipoMediaWhatsapp)
.Include(x => x.Mensagens.Where(m => m.Ativo))
.ThenInclude(x => x.TemplateMensagem)
.ThenInclude(t => t.Medias)
.ThenInclude(m => m.MediaWhatsapp)
.ThenInclude(m => m.TipoMediaWhatsapp)
.AsNoTracking()
.FirstOrDefaultAsync(l => l.Id == id && l.Ativo);
但是如果我执行完全相同的命令只是删除 AsNoTracking()
行,它会给我 3 条记录,包括活动的和非活动的。
但不活动的 EF 不会获取下面的 ThenInclude
。它改变了行为。
使用 AsNoTracking
它根据我在 Include
上使用的过滤器过滤数据
没有 AsNoTracking
它会给我所有数据,但它会过滤是否加载 ThenInclude
对象。
有谁知道这是否是正常行为,为什么会这样?
这在 Filtered include 文档中有某种解释:
Caution
In case of tracking queries, results of Filtered Include may be unexpected due to navigation fixup. All relevant entities that have been queried for previously and have been stored in the Change Tracker will be present in the results of Filtered Include query, even if they don't meet the requirements of the filter. Consider using NoTracking
queries or re-create the DbContext when using Filtered Include in those situations.
所以很可能在进行跟踪测试时您的上下文不干净。即使它是干净的,以防它用于执行其他查询,导航修正也可以加载一些不令人满意的过滤器实体 later 因为它跟踪(访问)所有被跟踪的实体.
一般来说,您不能依赖被跟踪实体的导航内容 属性,因为它可能会在上下文的生命周期内随时更新,直到上下文被处理或实体与更改跟踪器分离。如果您需要完全控制,要么不使用跟踪实体查询,要么不使用 DTO/ViewModel 等。投影查询和 select 正是您想要的(没有 Include
/ ThenInclude
,只是普通的 LINQ ).
不知道是不是应该这样,但是我觉得很奇怪,因为更改了查询结果。
当我执行下面的查询时,我得到的实体只有 2 个“Mensagens”实体,因为我只过滤活动,所以它是正确的,我的数据库中有 2 个活动实体和 1 个非活动实体。
return await context.Lancamentos
.Include(x => x.UsuarioCriacao)
.Include(x => x.Mensagens.Where(m => m.Ativo))
.ThenInclude(m => m.MensagemMedias)
.ThenInclude(m => m.MediaWhatsapp)
.ThenInclude(m => m.TipoMediaWhatsapp)
.Include(x => x.Mensagens.Where(m => m.Ativo))
.ThenInclude(x => x.TemplateMensagem)
.ThenInclude(t => t.Medias)
.ThenInclude(m => m.MediaWhatsapp)
.ThenInclude(m => m.TipoMediaWhatsapp)
.AsNoTracking()
.FirstOrDefaultAsync(l => l.Id == id && l.Ativo);
但是如果我执行完全相同的命令只是删除 AsNoTracking()
行,它会给我 3 条记录,包括活动的和非活动的。
但不活动的 EF 不会获取下面的 ThenInclude
。它改变了行为。
使用 AsNoTracking
它根据我在 Include
没有 AsNoTracking
它会给我所有数据,但它会过滤是否加载 ThenInclude
对象。
有谁知道这是否是正常行为,为什么会这样?
这在 Filtered include 文档中有某种解释:
Caution
In case of tracking queries, results of Filtered Include may be unexpected due to navigation fixup. All relevant entities that have been queried for previously and have been stored in the Change Tracker will be present in the results of Filtered Include query, even if they don't meet the requirements of the filter. Consider using
NoTracking
queries or re-create the DbContext when using Filtered Include in those situations.
所以很可能在进行跟踪测试时您的上下文不干净。即使它是干净的,以防它用于执行其他查询,导航修正也可以加载一些不令人满意的过滤器实体 later 因为它跟踪(访问)所有被跟踪的实体.
一般来说,您不能依赖被跟踪实体的导航内容 属性,因为它可能会在上下文的生命周期内随时更新,直到上下文被处理或实体与更改跟踪器分离。如果您需要完全控制,要么不使用跟踪实体查询,要么不使用 DTO/ViewModel 等。投影查询和 select 正是您想要的(没有 Include
/ ThenInclude
,只是普通的 LINQ ).