joh*_*y 5 3 c# entity-framework-core .net-core .net-core-3.1 ef-core-3.1
我正在寻找解决EntityFramework Core Bug 的方法。我正在尝试编写一个对自身进行过滤的查询。
免责声明: 我正在做一些比通过显式过滤更复杂的事情
userId,为了简单起见,我只是将它与硬编码值一起使用,因为确切的实现与我的问题无关。
protected override void OnModelCreating(ModelBuilder modelBuilder) =>
modelBuilder.Entity<ConversationSubscription>()
.HasQueryFilter(x => x.Conversation.ConversationSubscriptions
.Select(c => c.UserId).Contains(315)
);
Run Code Online (Sandbox Code Playgroud)
由于查询过滤器试图访问它正在过滤的实体,因此它最终陷入无限循环。由于我们使用的是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)
);
Run Code Online (Sandbox Code Playgroud)
然而,这会抛出一个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
);
Run Code Online (Sandbox Code Playgroud)
查询过滤器最初不支持访问导航属性或数据库集。看起来 EF Core 3.0 删除了这些限制(可能是因为每个 LINQ 查询模式的新单 SQL 语句),具有以下限制/错误:
AsNoTracking()并且AsTracking()- 不支持,这是有道理的,因为查询过滤器总是被转换成 SQL。
Include/ ThenInclude- 允许,但由于同样的原因被忽略。
IgnoreQueryFilters- 不支持。这可以被视为错误,因为它可以用于解决下一个案例。
通过导航属性或数据库集交叉引用过滤器(例如,实体A过滤器使用实体B,实体B过滤器使用实体A) - 原因StackOverflowException是过滤器试图相互使用。这是一个错误。
通过导航属性的自引用过滤器 - 与 #4 相同的错误,应该像 #6。
通过数据库集的自引用过滤器 - 支持(!),在过滤器子查询中总是被忽略。
话虽如此,幸运的是您的案例得到了#6 的支持,即您的第二次尝试只是不受支持AsNoTracking()并IgnoreQueryFilters()已删除:
modelBuilder.Entity<ConversationSubscription>().HasQueryFilter(x =>
this.Set<ConversationSubscription()
.Where(cs => cs.ConversationId == x.ConversationId)
.Select(c => c.UserId)
.Contains(315));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
268 次 |
| 最近记录: |