【问题标题】:How to load only base type in Entity Framework如何在实体框架中仅加载基类型
【发布时间】:2015-09-29 23:08:32
【问题描述】:

考虑以下情况:

我有另外两个继承的基类。 例如我们将有:

class Base
{

}
class DerivedA : Base
{

}
class DerivedB : Base
{

}

当我使用类似代码请求基本实体时

context.Base.Where(q => q.Id == id).First();

实体框架为每个派生实体生成一整套连接,导致查询性能低于可接受的水平。 我想要的是只加载基础实体而不将其加入派生实体。

我在这里找到的唯一解决方案是http://blogs.msdn.com/b/alexj/archive/2009/09/17/tip-35-how-to-write-oftypeonly-tentity.aspx。 但这对我不起作用。 EF 仍然会生成大量查询。

编写如下查询:

context.Base.Where(q => !(q is DerivedA) && !(q is DerivedB)).First();

不适合我,因为派生类型的数量不断增加。

除了我提到的之外,还有其他可能的解决方案吗?

【问题讨论】:

  • 您认为什么是“低于可接受的性能”?我很好奇你为什么想要一个基类?
  • 我想要的是只加载基础实体而不将其加入派生实体”:这是否意味着您只想要基础 part实体或您只想要 基本类型的实体?对于后者,请记住,查询需要连接到派生类型的表中以确定实体是否属于基本类型(基本上如果连接的结果为空,则实体属于基本类型,否则不是)。因此,在这种情况下,您无法避免连接(这是 TPT 继承的代价)。如果您只想要基础 part 投影可能是正确的方法。

标签: c# entity-framework entity-framework-4 entity-framework-4.1


【解决方案1】:

您正在使用 Table-per-type => EF 必须生成这些连接,因为它不知道您的实体到底是什么类型。如果您来自Base 的记录在DerivedA 表中有相关​​记录不得为该记录创建Base 实体的实例 - 必须创建@ 的实例987654325@,它需要进行连接才能获得这些知识。

长时间讨论为什么不允许这样做,而只是实体来自对象世界-它是原子数据结构,可以保存到多个表中,但对对象世界不可见。如果你持久化Base,你将加载回Base,但如果你持久化DerivedA,你将始终加载回DerivedA,而不仅仅是Base,因为它会破坏实体的原子性。

我没有尝试过,但我认为 ESQL OFTYPE ONLY 运算符也应该进行连接,以确保它确实加载了基础实体的真实实例,而不是派生实体的损坏实例。

Table-per-type 会产生缓慢的查询。 .NET 4.5 应该改进它,但我认为改进不会针对这些情况 - 我认为它们将针对派生类型和预测的 OfType

如果您只需要 Base 表中的数据,您最好的选择是:

【讨论】:

  • 如果您不在,我们 EF 新手会在哪里?大声笑是否有使用继承的特定方式/正确做法以及何时不使用?
  • 我了解 TPT 查询的性能可能和你一样——我们有很好的对象模型和大的 TPT 继承结构,我们在真实数据上的性能很糟糕——我们最后创建了特殊的数据库视图来获取信息我们需要(以及非常必要的连接)并将它们映射为单独的只读实体。
  • @Ladislav,我们能否为父级创建一个单独(但相似)的实体,并将其映射到同一张表?
【解决方案2】:

您可以引入一个没有进一步含义/功能的抽象中间类,所有派生类型都必须从中派生:

class Base
{

}
abstract class DerivedBase : Base
{

}
class DerivedA : DerivedBase 
{

}
class DerivedB : DerivedBase 
{

}

然后你可以做一个简单的查询,不管有多少派生类:

context.Bases
  .Where(b => !(b is DerivedBase))
  ...

【讨论】:

  • 这可能有效,但请注意,在 TPT 映射中,这将添加另一个表,该表将成为每个查询继承 DerivedBase 的对象的查询连接子句的一部分,在这种情况下,这将是全部其中。
  • 感谢@MarcL。 - 因为我只使用 TPH,所以我没有考虑过。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 2018-12-02
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
相关资源
最近更新 更多