首页 > 解决方案 > 实体框架 - 有条件地查询具有类型转换的相关实体

问题描述

我有两个班级:

public abstract class Conversation
{
    public int Id { get; set; }
}

public class PrivateConversation : Conversation
{
    public ICollection<User> Users { get; set; }
}

在 DbContext 中,有 DbSet:

public DbSet<Conversation> Conversations { get; set; }
public DbSet<PrivateConversation> PrivateConversations { get; set; }
public DbSet<User> Users { get; set; }

这会生成两个表:ConversationsUsers.

PrivateConversations 保存在表格中Conversations

现在查询发生错误:


// For some reason, I can only query `db.Conversations`, can not access `db.PrivateConversations`
var conversations = db.Conversations
  .Include(t => (t as PrivateConversation).Users)
  .Where(t => t is PrivateConversation)
  .Where(t => (t as PrivateConversation).Users.Any())
  .ToList();

告诉我,Users.Any()Users是空的。

我很困扰。如何查询其中与用户的所有私人对话?

附加信息:

我用过的包:

<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SQLServer" Version="2.2.6" />

运行时:.NET Core 2.2

<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>

标签: c#entity-framework.net-coreentity-framework-core

解决方案


我找不到任何有关此的文档。

根据包含派生类型,可以使用as运算符或显式转换。确实两者都适用于Include. 但是在标准 LINQ 运算符中,as运算符导致客户端评估和有问题的异常 - 客户端评估发生在导航属性尚未加载时(尽管Include. 在 3.0 中删除客户端评估的另一个原因。

回到你的问题。解决方案是使用显式强制转换:

.Where(t => ((PrivateConversation)t).Users.Any())

它正确地转换为 SQL,因此根本没有 NRE 问题。


推荐阅读