考虑以下案例:
我有另外两个继承的基类。 例如,我们将:
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();
由于衍生类型的数量不断增加,不适合我。
除了我提到的那些之外,还有其他可能的解决方案吗?
答案 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))
...