C# 代码首先加载嵌套而不递归
我有一张可以包含许多部分的表格。每个部分也可以包含许多部分。我希望以尽可能少的往返数据库的方式加载工作表、其部分和所有子部分。实际上,我认为这通常是1-2层的深度,但可能会达到16层。代码如下:C# 代码首先加载嵌套而不递归,c#,.net,ef-code-first,entity-framework-5,code-first,C#,.net,Ef Code First,Entity Framework 5,Code First,我有一张可以包含许多部分的表格。每个部分也可以包含许多部分。我希望以尽可能少的往返数据库的方式加载工作表、其部分和所有子部分。实际上,我认为这通常是1-2层的深度,但可能会达到16层。代码如下: using System; using System.Collections.Generic; using System.Linq; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity; public
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
public class Sheet {
public long Id { get; set; }
// more fields
public virtual IList<Section> Sections { get; set; }
}
public class Section {
public long Id { get; set; }
public long SheetId { get; set; }
[ForeignKey("SheetId")]
public virtual Sheet Sheet { get; set; }
public long? ParentId { get; set; }
[ForeignKey("ParentId")]
public virtual Section Parent { get; set; }
public virtual IList<Section> Sections { get; set; }
// more fields
}
public class MyDbContext : DbContext {
public DbSet<Sheet> Sheets { get; set; }
public DbSet<Section> Sections { get; set; }
public Sheet GetSheetConfiguration(long id) {
Configuration.LazyLoadingEnabled = false;
Sheet rtn;
rtn = Sheets.Find(id);
(Sections.Where(sect => sect.SheetId == id)).ToList();
return rtn;
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.ComponentModel.DataAnnotations.Schema;
使用System.Data.Entity;
公开课程表{
公共长Id{get;set;}
//更多领域
公共虚拟IList节{get;set;}
}
公共课组{
公共长Id{get;set;}
公共长SheetId{get;set;}
[外键(“SheetId”)]
公共虚拟图纸{get;set;}
公共长?父ID{get;set;}
[ForeignKey(“ParentId”)]
公共虚拟节父项{get;set;}
公共虚拟IList节{get;set;}
//更多领域
}
公共类MyDbContext:DbContext{
公共DbSet表{get;set;}
公共DbSet节{get;set;}
公共图纸GetSheetConfiguration(长id){
Configuration.LazyLoadingEnabled=false;
薄板rtn;
rtn=工作表。查找(id);
(Sections.Where(sect=>sect.SheetId==id)).ToList();
返回rtn;
}
}
这将创建所需的表结构:
工作表:Id(主键)。。。
部分:Id(主键)、SheetId(非空)、ParentId(空)
GetSheetConfiguration方法加载与该工作表相关的所有部分,并让EF对其进行排序。除了所有部分也在Sheet.Sections中之外,它可以获得正确的关系。(我想为每个部分设置SheetId,以避免递归查询。)如何告诉EF在工作表级别仅使用ParentId=null的部分?
-列表项您无法避免
Sheet.Sections
集合中会充满所有节,因为这就是Sheet.Sections
和Section.Sheet
之间的关系所描述的:它应该包含所有节,而不仅仅是ParentId==null
的“根节”。实体框架基于关系修复填充此集合,您不能禁用或配置此行为
解决此问题的一个选项是引入一个额外的集合属性,该属性从Sheet.Sections
导航属性中读取过滤后的数据,并且不映射到数据库以检索根节列表,如下所示:
public class Sheet {
public long Id { get; set; }
// more fields
public virtual IList<Section> Sections { get; set; }
public IEnumerable<Section> RootSections
{
get { return Sections.Where(sect => sect.ParentId == null); }
}
}
。。。您可以使用:
Sections.Where(sect => sect.SheetId == id).Load();
Load
是一个void
方法,它只将请求的实体加载到上下文中。它节省了创建不必要的列表
集合的开销。您无法避免工作表.Sections
集合被所有节填满,因为这就是工作表.Sections
和工作表.Sheet
之间的关系所描述的:它应该有所有的节,不仅是ParentId==null的“根节”。实体框架基于关系修复填充此集合,您不能禁用或配置此行为
解决此问题的一个选项是引入一个额外的集合属性,该属性从Sheet.Sections
导航属性中读取过滤后的数据,并且不映射到数据库以检索根节列表,如下所示:
public class Sheet {
public long Id { get; set; }
// more fields
public virtual IList<Section> Sections { get; set; }
public IEnumerable<Section> RootSections
{
get { return Sections.Where(sect => sect.ParentId == null); }
}
}
。。。您可以使用:
Sections.Where(sect => sect.SheetId == id).Load();
Load
是一个void
方法,它只将请求的实体加载到上下文中。它节省了创建不必要的列表
集合的开销。您为GetSheetConfiguration
发布的代码是否正确?我不明白这行(Sections.Where…
的目的是加载该表的所有部分,然后让EF进行排序。正如@Slauma所建议的,应该更清楚地说Sections.Where(sect=>sect.SheetId==id.Load()
您为GetSheetConfiguration
发布的代码是否正确?我不明白这行(Sections.Where…
的目的是加载该表的所有部分,然后让EF进行排序。正如@Slauma所建议的,应该更清楚地说Sections.Where(sect=>sect.SheetId==id.Load()代码>