gpt4 book ai didi

c# - .NET Core 自访问查询过滤器

转载 作者:行者123 更新时间:2023-12-04 02:36:13 26 4
gpt4 key购买 nike

我正在寻找解决 EntityFramework Core Bug 问题的方法.我正在尝试编写一个对自身进行过滤的查询。

Disclaimer: I'm doing something a bit more complex than filtering by an explicit userId, I am just using this with a hard-coded value for simplicity, as the exact implementation isn't relevant to my question.

protected override void OnModelCreating(ModelBuilder modelBuilder) =>
modelBuilder.Entity<ConversationSubscription>()
.HasQueryFilter(x => x.Conversation.ConversationSubscriptions
.Select(c => c.UserId).Contains(315)
);

由于查询过滤器试图访问它正在过滤的实体,它最终陷入无限循环。由于我们使用的是 ModelBuilder 而不是 DbSet,因此无法将其标记为 IgnoreQueryFilters

鉴于此,我尝试使用当前上下文来过滤自身:

modelBuilder.Entity<ConversationSubscription>().HasQueryFilter(x => 
this.Set<ConversationSubscription().AsNoTracking().IgnoreQueryFilters()
.Where(cs => cs.ConversationId == x.ConversationId)
.Select(c => c.UserId)
.Contains(315)
);

但是,这会抛出一个 InvalidOperationException,很可能是因为我们试图在 OnModelCreating 完成之前使用上下文。

我觉得如果我能以某种方式将 ConversationSubsriptions 选择为匿名类型,这样我就可以解决这个问题,这样它们就不会被过滤。

编辑:我尝试使用匿名类型破解此问题,但没有成功。

modelBuilder.Entity<ConversationSubscription>().HasQueryFilter(c =>
x => x.Conversation.Messages.Select(m => new {
Value = m.Conversation.ConversationSubscriptions.Distinct()
.Select(cs => cs.UserId).Contains(c.Variable(this._userId))
}).FirstOrDefault().Value
);

最佳答案

查询过滤器最初不支持访问导航属性或数据库集。看起来 EF Core 3.0 删除了这些限制(可能是因为新的 Single SQL statement per LINQ query 模式),但存在以下限制/错误:

  1. AsNoTracking()AsTracking() - 不受支持,这是有道理的,因为查询过滤器总是转换为 SQL。

  2. Include/ThenInclude - 允许,但出于同样的原因被忽略。

  3. IgnoreQueryFilters - 不支持。这可以被视为错误,因为它可以用来解决下一个案例。

  4. 交叉引用过滤器(例如实体 A 过滤器使用实体 B 和实体 B 过滤器使用实体 A) 通过导航属性或数据库集 - 导致 StackOverflowException 因为过滤器试图相互使用。这是一个错误。

  5. 通过导航属性自引用过滤器 - 与 #4 相同的错误,应该与 #6 相同。

  6. 通过数据库集的自引用过滤器 - 支持(!),在过滤器子查询中始终被忽略。

综上所述,幸运的是,#6 支持您的案例,即您的第二次尝试只删除了不受支持的 AsNoTracking()IgnoreQueryFilters():

modelBuilder.Entity<ConversationSubscription>().HasQueryFilter(x => 
this.Set<ConversationSubscription()
.Where(cs => cs.ConversationId == x.ConversationId)
.Select(c => c.UserId)
.Contains(315));

关于c# - .NET Core 自访问查询过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61706122/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com