如何在Entity Framework中仅加载基类型

时间:2012-07-19 15:45:19

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

考虑以下案例:

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

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();
由于衍生类型的数量不断增加,

不适合我

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

2 个答案:

答案 0 :(得分:5)

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

长期讨论为什么不允许这样做,但是简单的实体来自对象世界 - 它是原子数据结构,可以保存到多个表但对于对象世界是不可见的。如果您坚持Base,则会加载Base,但如果您坚持DerivedA,则会始终加载回DerivedA,而不仅仅Base,因为它会中断实体的原子性。

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

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

如果您只想要来自Base表的数据,那么您最好的选择是:

答案 1 :(得分:0)

您可以引入一个抽象的中间类,没有其他含义/函数,所有派生类型都必须从中派生出来:

class Base
{

}
abstract class DerivedBase : Base
{

}
class DerivedA : DerivedBase 
{

}
class DerivedB : DerivedBase 
{

}

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

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