【问题标题】:Getting records of specific type获取特定类型的记录
【发布时间】:2014-06-15 15:44:53
【问题描述】:

我有两个班级:

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 和两个 DBSet。基本上,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; }
    }

【问题讨论】:

  • 我设法通过在每个类中添加 [Table("Items", Schema = "Datamodel")] 之类的内容来创建单独的表。所以,这不是一个真正的问题,尽管我必须决定我喜欢什么。

标签: c# types visual-studio-2013 poco entity-framework-6


【解决方案1】:

由于涉及到继承,可能有一个类型描述符针对您存储的可以过滤的实体,它看起来就像您只有一个表,您有一个名为 Table Per Hierachy (TPH) 的排列

查看此链接:

http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx

它指的是一个OfType&lt;T&gt;() 方法,它可能会让你出价。

编辑(更正为工作示例)

使用类似的用法:

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]}

【讨论】:

  • TPH, TPT... 没有区别。已经发现如何转移到 TPT,但问题仍然存在,我不想选择所有基本项目。只是根项目。 OfType 仍然是所有结果,因为它们在技术上都是 BaseItem 类型。 (继承与否。)
  • 知道了!我有点困惑为什么你不能只查询 Items 集合(所有根的集合)?您的 DbSet 是什么样的?
  • 我在上面添加了 DBContext 和 DBSet 定义。问题是我可以在数据库中有很多记录。 db.Items 将返回 BaseItem 和 ChildItem 记录,而我只需要 BaseItem 记录。事情变得更加复杂,因为我有更多继承自 BaseItem 或 ChildItem 的类/表。
  • 通过一个简单的案例完成并确认仅检索根项目。
  • 我认为它可能会缩短为context.Items.Except(context.Items.OfType&lt;ChildItem&gt;());,因为它们都是 BaseItem 类。 (测试:是的,它有效!)最重要的是,它选择了所有根项目、IE、从 BaseItem 派生的任何东西,但不是 ChildItem。这是我需要的。
猜你喜欢
  • 2016-01-15
  • 2011-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-19
  • 1970-01-01
相关资源
最近更新 更多