C# 如何在实体框架中仅加载基类型
考虑以下情况: 我有另外两个继承的基类。 例如,我们将有:C# 如何在实体框架中仅加载基类型,c#,entity-framework,entity-framework-4,entity-framework-4.1,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() 实体框架生成一整套到每个派生实体的连接,从而导致查询性能低于可接受的水平。 我想要的是只加载基本实体,而不将其连接到派生实体 这里描述了我找到的唯一解决方案。 但这对我不起作用。EF仍然生成
class Base
{
}
class DerivedA : Base
{
}
class DerivedB : Base
{
}
当我请求代码如下的基本实体时
context.Base.Where(q=>q.Id==Id.First()
实体框架生成一整套到每个派生实体的连接,从而导致查询性能低于可接受的水平。
我想要的是只加载基本实体,而不将其连接到派生实体
这里描述了我找到的唯一解决方案。
但这对我不起作用。EF仍然生成巨大的查询
编写查询,如:
context.Base.Where(q => !(q is DerivedA) && !(q is DerivedB)).First();
也不适合我,因为派生类型的数量不断增加
除了我提到的那些之外,还有什么可能的解决方案吗?您正在使用每种类型的表=>EF必须生成这些连接,因为它不知道您的实体实际上是什么类型的。如果来自
Base
的记录在DerivedA
表中有相关记录,则它不能为该记录创建Base
实体的实例-它必须创建DerivedA
的实例,并且它需要进行连接以获得此知识
这是一个长期的讨论,为什么这是不允许的,但只是实体是从对象世界-它是原子数据结构,可以保存到多个表,但这是不可见的对象世界。如果你坚持一个Base
,你将加载一个Base
,但是如果你坚持DerivedA
,你将始终加载DerivedA
,而不仅仅是Base
,因为它会破坏实体的原子性
我没有尝试过,但我假设ESQLof type ONLY
操作符也应该进行连接,以确保它确实加载了基本实体的真实实例,而不是派生实体的损坏实例
每种类型的表都会生成较慢的查询。NET4.5应该会改进它,但我认为改进不会针对这些情况——我认为它们会针对派生类型和预测的of type
如果您只需要Base
表中的数据,最好的选择是:
- 手工编写的SQL-联接或联合中的投影
- .NET4.5和Linq中的投影
class Base
{
}
abstract class DerivedBase : Base
{
}
class DerivedA : DerivedBase
{
}
class DerivedB : DerivedBase
{
}
然后,您可以进行简单的查询,不知道存在多少派生类:
context.Bases
.Where(b => !(b is DerivedBase))
...
您认为什么是“低于可接受的性能”?我很好奇为什么你想要一个基类?“我想要的是只加载基本实体,而不将其连接到派生实体”:这意味着你只需要实体的基本部分,还是只需要基本类型的实体?对于后者,请记住,查询需要连接到派生类型的表中,以确定实体是否为基类型(基本上,如果连接的结果为空,则实体为基类型,否则不是)。因此,在这种情况下,您无法避免连接(这是TPT继承的代价)。如果你只想要基本部分,a投影可能是正确的方法。如果你不在,我们EF新手会在哪里?lol有没有一种特殊的方法/适当的实践来使用继承以及何时不使用?我了解到TPT查询的性能可能与您的方法相同-我们有一个很好的对象模型,具有大的TPT继承结构,并且我们在真实数据上的性能很差-我们最终为我们需要的信息创建了特殊的数据库视图(和非常必要的连接)并将它们映射为单独的只读实体。@Ladislav,我们可以创建单独的(但类似的)实体吗实体到父对象,并将其映射到同一个表?这可能会起作用,但请注意,在TPT映射中,这将添加另一个表,该表将成为继承
DerivedBase
的对象的每个查询中的查询联接子句的一部分,在本例中,这将是所有对象。Thanx@MarcL。-因为我只使用TPH,所以我没有考虑到这一点。