【发布时间】: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