【问题标题】:How to load all related EF entities in preparation for serialization如何加载所有相关的 EF 实体以准备序列化
【发布时间】:2015-06-17 00:46:22
【问题描述】:

谁能告诉我如何(优雅地)加载所有相关的实体对象以准备序列化到磁盘?

我有一个表会话。一个会话可以有多个记录在记录表中。此外,每个 Recording 可以有多个 RecordedFiles,它们位于 RecordedFiles 表中。

EF 类看起来像这样(为简单起见):

[Serializable]
public partial class Session
{
    public Session()
    {
       this.Notes = new HashSet<Note>();
        this.Recordings = new HashSet<Recording>();
    }

    public System.Guid SessionGUID { get; set; }
     public int SessionNum { get; set; }
    public virtual ICollection<Note> Notes { get; set; }
   public virtual ICollection<Recording> Recordings { get; set; }
}

[Serializable]
public partial class Recording
{
    public Recording()
    {
        this.RecordedFiles = new HashSet<RecordedFile>();
         this.ProcessedFiles = new HashSet<ProcessedFile>();
    }

    public System.Guid RecordingGUID { get; set; }
    public int RecordingNumber { get; set; }
    public System.Guid SessionGUID { get; set; }
     public virtual ICollection<ProcessedFile> ProcessedFiles { get; set; }   
    public virtual ICollection<RecordedFile> RecordedFiles { get; set; }
    public virtual Session Session { get; set; }
   }

最初,我使用的是延迟加载,经过反复试验,我注意到我无法序列化所有内容,除非我在序列化之前碰巧在调试器中展开了集合。这是有道理的:通过延迟加载,实体在需要之前不会被拉出。但显然,我不能总是单步调试调试器并这样做!我的下一个想法是使用“Eagerly Loading”。例如,请参阅https://msdn.microsoft.com/en-US/data/jj574232。但是如果你看这个,你会发现你需要有“包含”语句。我相信我必须有多个包含语句(请参阅:Loading all the children entities with entity framework)来涵盖来自 Session(录音和笔记)的不同分支。情况比我展示的还要糟糕:有多个分支从 Session 中脱落,而且它们比我说的更深。也就是说,一个 Session 可能有一个 Recordings 的集合,而 Recordings 又是一个 RecordedFiles 的集合,而这些又是一个等等。

如果我必须写一些丑陋的表达式,例如: 会话 session = context.Sessions.Include("Recordings.RecordedFiles").Include("Recordings.ProcessedFiles").Include("Equipment.StereoEquipment").Include("Notes").Where(p => p.GUID = = ####).FirstOrDefault();

我会的。但我猜有一些优雅的方式可以说,“加载与这个给定会话相关的所有实体”。有人可以启发我吗?请注意,在上面的怪物中,我都包含“Recordings.RecordedFiles”和“Recordings.ProcessedFiles”。也就是说,Session 有一个 Recordings 的集合。每个 Recording 都有 RecordedFiles 和 ProcessedFiles 的集合。最好说“包括录音。{所有子集合}

谢谢,

戴夫

编辑:我应该指出避免多个“包含”的另一个原因是,如果数据库发生更改(例如,在 Recordings 下有另一个表或集合),则必须重写代码。可能很难跟踪。

【问题讨论】:

  • 还有第三种选择:显式加载。 msdn.microsoft.com/en-us/library/vstudio/…
  • 谢谢 Jeroen,我看到了第三个选项。但是,再一次,我无法自动获取每个相关实体。
  • 自从写了原始问题后,我找到了第4种方法:使用存储过程。至少攻击性代码会被隐藏在一个地方并且更容易更改。它可能会带来更好的性能。

标签: entity-framework serialization lazy-loading eager-loading


【解决方案1】:

恐怕没有内置的方法可以做你想做的事。您可以使用反射做一些事情,在其中枚举所有属性并自己加载它们。像这样:

How can I recursively Include ALL navigable properties to emulate Lazy Loading

【讨论】:

  • 感谢马特的想法。我阅读了您的链接并尝试了您的示例代码。不幸的是,我遇到了与最后一位评论者(user1265146)相同的问题。也就是说,我收到了带有消息的 'System.ArgumentException':“'People' 类型的属性 'RowVersion' 不是导航属性。Reference 和 Collection 方法只能与导航属性一起使用。使用 Property 或 ComplexProperty 方法
  • 嘿戴夫,我已经更新了链接上的脚本,应该处理这些非 dbreference 对象。
  • 我最终选择了所有丑陋的 .Include 语句,因为(1)我时间紧迫,(2)我觉得我没有完全理解你的代码。希望我有机会重温它,所以我感谢您抽出时间更新您的脚本。干杯!
  • 没问题,如果您决定看一看并需要一些指导来理解它,请给我一个呐喊!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 2016-08-01
  • 2016-04-16
相关资源
最近更新 更多