如何加载所有相关的 EF 实体以准备序列化
How to load all related EF entities in preparation for serialization
有人能告诉我如何(优雅地)加载所有相关实体对象以准备序列化到磁盘吗?
我有一个 table 会话。一个 Session 可以有多个 Recordings,它们在 Recordings Table 中。更进一步,每个Recording可以有多个RecordedFiles,在RecordedFilestable中。
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 for example. But if you look at this, you see that you need to have "include" statements. I believe I would have to have multiple include statements (see: Loading all the children entities with entity framework) 以涵盖来自 Session(录音和笔记)的不同分支。而且情况比我展示的还要糟糕:会话中有多个分支,而且它们比我透露的要深。也就是说,一个 Session 可能有一个 Recordings 集合,而 RecordingFiles 又是一个 RecordedFiles 集合,等等
如果我必须写一些丑陋的表达方式,例如:
会话 session = context.Sessions.Include("Recordings.RecordedFiles").Include("Recordings.ProcessedFiles").Include("Equipment.StereoEquipment").Include("Notes").Where(p => p.GUID == ####).FirstOrDefault();
我会的。但我猜有一些优雅的说法,"Load all entities related to this given Session"。有人可以启发我吗?请注意,在上面的怪物中,我同时包含 "Recordings.RecordedFiles" 和 "Recordings.ProcessedFiles"。也就是说,Session 有一个 Recordings 的集合。每个 Recording 都有一个 RecordedFiles 和 ProcessedFiles 的集合。最好说“包括录音。{所有子集合}
谢谢,
戴夫
编辑:我应该指出避免使用多个 "includes" 的另一个原因是如果数据库发生变化(例如在 Recordings 下有另一个 table 或集合),代码将必须重写。可能很难跟踪这一点。
恐怕没有内置的方法来做你想做的事。你可以用反射来做一些事情,你可以在其中枚举所有属性并自己加载它们。像这样:
How can I recursively Include ALL navigable properties to emulate Lazy Loading
有人能告诉我如何(优雅地)加载所有相关实体对象以准备序列化到磁盘吗?
我有一个 table 会话。一个 Session 可以有多个 Recordings,它们在 Recordings Table 中。更进一步,每个Recording可以有多个RecordedFiles,在RecordedFilestable中。
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 for example. But if you look at this, you see that you need to have "include" statements. I believe I would have to have multiple include statements (see: Loading all the children entities with entity framework) 以涵盖来自 Session(录音和笔记)的不同分支。而且情况比我展示的还要糟糕:会话中有多个分支,而且它们比我透露的要深。也就是说,一个 Session 可能有一个 Recordings 集合,而 RecordingFiles 又是一个 RecordedFiles 集合,等等
如果我必须写一些丑陋的表达方式,例如: 会话 session = context.Sessions.Include("Recordings.RecordedFiles").Include("Recordings.ProcessedFiles").Include("Equipment.StereoEquipment").Include("Notes").Where(p => p.GUID == ####).FirstOrDefault();
我会的。但我猜有一些优雅的说法,"Load all entities related to this given Session"。有人可以启发我吗?请注意,在上面的怪物中,我同时包含 "Recordings.RecordedFiles" 和 "Recordings.ProcessedFiles"。也就是说,Session 有一个 Recordings 的集合。每个 Recording 都有一个 RecordedFiles 和 ProcessedFiles 的集合。最好说“包括录音。{所有子集合}
谢谢,
戴夫
编辑:我应该指出避免使用多个 "includes" 的另一个原因是如果数据库发生变化(例如在 Recordings 下有另一个 table 或集合),代码将必须重写。可能很难跟踪这一点。
恐怕没有内置的方法来做你想做的事。你可以用反射来做一些事情,你可以在其中枚举所有属性并自己加载它们。像这样:
How can I recursively Include ALL navigable properties to emulate Lazy Loading