我有两个班级:
public class BaseItem
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual List<ChildItem> Children { get; set; }
}
public class ChildItem : BaseItem
{
public virtual BaseItem Parent { get; set; }
public ChildItem() { }
}
我为这两个类创建了一个DBContext和两个DBSets。基本上,BaseItem是一个根类,其下面有一个子项树。数据库将包含数十个这样的树 实体框架将为这两个类创建一个表,我不喜欢,但现在它已经足够好了。 (我可以告诉EF以简单的方式将其分成两个表吗?)
我的问题是只选择根项,因此选择类BaseItem而不是类ChildItem。像
这样的东西db.Items.Where(i=>i.GetType()==typeof(BaseItem))
这不起作用,因为EF无法将GetType方法转换为对数据库有意义的方法。所以我要么在Where子句之前加.ToList()
,要么找到更好的解决方案
由于我不想在过滤500个根项目之前检索所有1,000,000条记录,因此我需要更好的解决方案。什么是更好的解决方案?
这是定义DBContext(db变量)和DBSet(db的Items属性)的方式。
public class Datamodel : DbContext
{
public Datamodel() : base("name=Datamodel") { }
public virtual DbSet<BaseItem> Items { get; set; }
public virtual DbSet<ChildItem> Children { get; set; }
}
答案 0 :(得分:1)
由于涉及继承,可能存在针对您存储的可以过滤的实体的类型描述符,并且看起来您只有一个表,您有一个名为Table Per Hierachy(TPH)的排列
检查此链接:
它指的是OfType<T>()
方法,可以进行出价。
编辑(更正为工作示例)
使用类似:
var rootItems = context.Items.OfType<BaseItem>().Except(context.Items.OfType<ChildItem>());
在TPH场景中只撤回根项目。
SQL:
SELECT
1 AS [C1],
[Except1].[Discriminator] AS [C2],
[Except1].[Id] AS [C3],
[Except1].[Name] AS [C4],
[Except1].[Parent_Id] AS [C5]
FROM (SELECT
[Extent1].[Discriminator] AS [Discriminator],
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Parent_Id] AS [Parent_Id]
FROM [dbo].[BaseItems] AS [Extent1]
WHERE [Extent1].[Discriminator] IN (N'ChildItem',N'BaseItem')
EXCEPT
SELECT
N'ChildItem' AS [C1],
[Extent2].[Id] AS [Id],
[Extent2].[Name] AS [Name],
[Extent2].[Parent_Id] AS [Parent_Id]
FROM [dbo].[BaseItems] AS [Extent2]
WHERE [Extent2].[Discriminator] = N'ChildItem') AS [Except1]}