4

请考虑以下情况:如何在实体框架中仅加载基类型

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

class Base 
{ 

} 
class DerivedA : Base 
{ 

} 
class DerivedB : Base 
{ 

} 

当我请求基地实体与代码等

context.Base.Where(Q => q.Id == ID)。首先();

实体框架为每个派生实体生成一整套连接,这会导致查询的可接受性能低于下列值。 什么我想要的只是加载基本实体而不加入派生的。

我在这里找到的唯一解决方案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(); 

不适合我要么是由于不断增加的派生类型的量。

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

+1

你认为什么是“低于可接受的性能”?我很好奇你为什么想要一个基类? – 2012-07-19 15:50:28

+0

“*我想要的只是加载基本实体而不将它加入派生的实体*”:这是否意味着您只需要实体的基本*部分*,或者您只希望*为基本类型*的实体?对于后者,请记住,查询需要连接到派生类型的表中以确定实体是否为基本类型(基本上,如果连接的结果为空,则实体为基本类型,否则不是)。所以,你无法避免这种情况下的连接(这是TPT继承的价格)。如果你只想要基础*部分*投影可能是正确的方法。 – Slauma 2012-07-19 16:13:28

回答

5

您正在使用Table-per-type => EF必须生成这些连接,因为它不知道您的实体是什么类型。如果从Base您的记录有相关的记录中DerivedA它不能该记录的创造Base实体的实例 - DerivedA它必须创建实例,并将其需要做出加入得到这方面的知识。

这是一个长时间的讨论,为什么这是不允许的,但单纯的实体是由客观世界 - 它是原子数据结构,它可以保存到多个表,但是这是不可见的对象世界。如果你坚持Base,你将加载一个Base,但如果你坚持DerivedA,你总是会加载回DerivedA,而不会只加载Base,因为它会破坏实体的原子性。

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

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

如果你想从Base表中只有数据你最好的选择是:

+0

如果你不在身边,我们EF新手会在哪里?大声笑有没有一种特殊的方式/适当的做法来使用继承,什么时候不? – 2012-07-19 16:19:03

+0

我了解了TPT查询的性能可能与您的方式相同 - 我们拥有很好的对象模型,并且具有很大的TPT继承结构,而且我们在真实数据上的表现非常糟糕 - 我们以创建特殊数据库视图来获取我们需要的信息必要)并将它们映射为单独的只读实体。 – 2012-07-19 16:22:53

+0

@Ladislav,我们可以创建一个单独的(但相似的)实体给父,并将其映射到同一个表? – Iravanchi 2014-04-14 09:52:18

0

从所有派生类型必须得到你可以引入没有进一步的意义/功能的抽象中介类:

class Base 
{ 

} 
abstract class DerivedBase : Base 
{ 

} 
class DerivedA : DerivedBase 
{ 

} 
class DerivedB : DerivedBase 
{ 

} 

然后,你可以做一个简单的查询没有马瑟如何许多派生类存在:

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

这可能会起作用,但请注意,在TPT映射中,这将添加另一个表,该表将成为每个查询继承“DerivedBase”的每个查询中的查询连接子句的一部分,在这种情况下,它们就是所有这些表。 – 2017-07-31 19:33:56

+0

Thanx @MarcL。 - 因为我只使用TPH,所以我没有想到这一点。 – springy76 2017-08-01 19:05:39