Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在实体框架中仅加载基类型_C#_Entity Framework_Entity Framework 4_Entity Framework 4.1 - Fatal编程技术网

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
,因为它会破坏实体的原子性

我没有尝试过,但我假设ESQL
of 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,所以我没有考虑到这一点。