【问题标题】:Entity Framework, eager loading and big object graph实体框架、急切加载和大对象图
【发布时间】:2014-04-02 10:16:56
【问题描述】:

我有一个 WPF 项目,该项目适用于带有项目的本地数据库。本地数据库稍后与服务器同步。 每个项目都有多个系统,每个系统都有多个“标签”。标签有产品,产品由多种材料组成,结构相当先进。一个简单的结构是这样的:

  • 项目
    • 系统
      • 标签
        • 产品
          • 材料1
          • 材料2
          • 材质3
        • 标签要求
      • 系统要求

我现在有两个问题需要解决。

  1. 加载项目时,我需要从数据库加载整个项目并使用本地副本,直到用户保存它。当我尝试急切加载时,它会花很长时间,我发现你不应该有很多包含,因为它不利于性能。 我应该如何将深层结构加载到内存中?

  2. 我需要将其加载到内存中的原因是,用户可以处理副本,然后在给定点将其保存到数据库中。我有多个计算函数,取决于树的不同部分。我的结论让我认为我需要将整个项目(或至少一个系统)发布到业务层,因为所有数据都可以在本地(内存)编辑

我是不是想错了?也许有一种方法可以将整个数据库(因为它不是那么大而且它已经是本地的)加载到 memorydb 并在实体框架中具有本地上下文。当用户保存时,我将其保存到真实数据库中,然后进行同步。

正如你所听到的,我不确定如何解决这个问题,所以欢迎任何提示

【问题讨论】:

  • 对象图有多大,总共有多少行?
  • 我不确定最终版本,但我现在有大约 20 个不同的类可以由用户(或计算)更改,而且还有“更多”。其中一些具有导航属性,让我们说具有用户不可更改的值的材料。编辑:忘记行数。 Total 很难说,因为用户可以为不同的条件添加计算值,这可能多达 50 个。所以有些类存在 50 个版本(仅计算)

标签: c# wpf entity-framework eager-loading


【解决方案1】:

当使用 .Include 和 N:M 关系时,实体框架执行左外连接,返回的行数可能比实际需要的多得多。

有一种技术可以更精确地加载对象图。它有很多编码并且非常丑陋,但可以提供更好的性能。该技术详细描述(带有示例)in this blog

我的技术是每个级别查询一次,然后链接应用程序中的对象。

这种技术在 NHibernate 等其他 ORM 中是自动(惰性)的,作为“批量加载”,但在 EntityFramework 中您必须手动完成。

【讨论】:

  • 嗨!看起来链接已损坏...您可以在这里分享您的解决方案或修复链接吗?
【解决方案2】:

我和你有同样的问题,我用大量 Include 语句解决问题的方法是将它们分成小组。

而不是这个:

scarRevision = db.ScarRevisions
.Include(s => s.Author)
.Include(s => s.Scar.Author)
.Include(s => s.Scar.LockedBy)
.Include(s => s.Scar.Part)
.Include(s => s.Scar.Supplier)
.Include(s => s.ScarGeneralSection.GeneralSectionAttachments)
.Include(s => s.ScarGeneralSection.SupplierContacts.Select(sc => sc.Contact))
// on and on and on...
.FirstOrDefault(s => s.Scar.ScarNumber == scarNumber && s.RevisionNumber == revisionNumber);

我用这个:

scarRevision = db.ScarRevisions
.Include(s => s.Author)
.Include(s => s.Scar.Author)
.FirstOrDefault(s => s.Scar.ScarNumber == scarNumber && s.RevisionNumber == revisionNumber);

scarRevision = db.ScarRevisions
.Include(s => s.Scar.LockedBy)
.Include(s => s.Scar.Part)
.FirstOrDefault(s => s.Scar.ScarNumber == scarNumber && s.RevisionNumber == revisionNumber);

scarRevision = db.ScarRevisions
.Include(s => s.Scar.Supplier)
.FirstOrDefault(s => s.Scar.ScarNumber == scarNumber && s.RevisionNumber == revisionNumber);

它将我的查询从将近 20 秒减少到仅 3 秒。仍然有点太多,但比以前好近 10 倍。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 2012-02-07
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多