c# - 实体框架 - 有条件地查询具有类型转换的相关实体
问题描述
我有两个班级:
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; }
这会生成两个表:Conversations
和Users
.
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>
解决方案
我找不到任何有关此的文档。
根据包含派生类型,可以使用as
运算符或显式转换。确实两者都适用于Include
. 但是在标准 LINQ 运算符中,as
运算符导致客户端评估和有问题的异常 - 客户端评估发生在导航属性尚未加载时(尽管Include
. 在 3.0 中删除客户端评估的另一个原因。
回到你的问题。解决方案是使用显式强制转换:
.Where(t => ((PrivateConversation)t).Users.Any())
它正确地转换为 SQL,因此根本没有 NRE 问题。