如何解决使用TPH和复杂类型的初始非常慢的EF实体调用?

时间:2019-04-01 14:08:17

标签: entity-framework entity-framework-6 dapper

我正在使用EF6

我有一个通用表,该表使用“每个层次的表”方法保存不同类型的类对象的数据。另外,这些类对象使用复杂的类型来为其属性定义类型。

因此,使用一个虚构的示例,

表=人员

“老师的麦克”是Person类型为“老师”的Person的“老师”实例

“教师”实例具有2个属性,complextypePersonalDetails和complextypeAddress。

complextypePersonalDetails包含      名,姓和年龄。

complextypeAddress包含      房屋名称,街道,镇,市,县。

我承认这种设计可能是最上层的,问题可能出在我的制作上,但除此之外,我想检查一下我是否可以在改写EF6之前再使用它。

我正在使用JetBrains DotTrace对代码进行性能分析。

在第一个电话上说        personTeacher = db.person.OfType()。First()

我得到了大约150,000ms的巨大延迟

周围:

     SerializedGeneratedViewOfType (150,000ms)
          TryGenerateQueryViewOfType
               GenerateTypeSpecificQueryView
                    GenerateQueryViewForSingleExtent
                        GenerateQueryViewForExtentAndType
                           GenerateViewsForExtentAndType
                              GenerateViewComponents
                                 EnsureExtentIsFullyMapped (90,000ms)
                                 GenerateCaseStatements    (60,000ms)

我使用创建SQL的“ InteractivePreGeneratedViews” nuget包创建了一个预生成的视图。但是即使如此,我仍然需要引起我的第一击。此外,每次重新启动Webserver / Website / AppPool时,这种情况似乎都会发生。

我不能完全确定EF流程,但是我想Web应用程序启动时会发生其他形式的运行时编译或缓存。这可能在哪里发生,有没有一种我可以用来预先生成/预编译/预缓存此问题的主动方法。

从中期来看,我们将在Dapper或EF.Core中重写此代码。所以现在,对可以做什么有什么想法?

谢谢。

1 个答案:

答案 0 :(得分:3)

我之前对此进行了评论,但撤回了它,但只是同意“这种设计可能太过头了,问题可能出在我身上”,但我想我可以看看是否有人参与进来。

最初的启动成本是由于EF需要解析您的架构映射。第一次访问上下文中的DBSet时,这种情况就会发生一次。您可以通过在应用程序启动时执行查询来缓解这种情况,即

void Application_Start(object sender, EventArgs e)
{
  // Initialization stuff...

  using (var context = new MyContext())
  {
     var result = context.MyTable.Any(); // Spin up will happen here, not when the first user attempts to access a query.
  }
}

实际上,您需要对DbContext运行查询以解决映射,只是一个新的操作就无法完成。

对于更大或更复杂的模式,您还可以利用有限的上下文,其中每个上下文针对应用程序的特定区域映射一组特定的关系。上下文越不复杂/不全面,则其初始化速度越快。

就设计而言,TPH用于表示继承,这是您需要在相似实体之间建立“ is-a”关系的地方。关系模型和按定义的ORM可以支持这一点,但是它们更适合于“具有”关系。与其建立模型“是一个有地址的人”,不如将关系最好地映射为一个人可能“有一个地址”。我已经在一个由工程师团队设计的系统上工作,该系统由6个表表示具有动态规则的整个报告系统。老实说,这些设计是一场噩梦。