您如何急切加载实体可能拥有的所有子集合?

时间:2016-07-06 09:26:23

标签: c# entity-framework

我有这个型号:

public class Person
{
    public string Name { get; set; }
    public Person Parent { get; set; }
    public virtual ICollection<Person> Children { get; set; }
} 

我的问题是:无论孩子有多深,我如何归还所有孩子?例如,我可以有一个人Alice,他有一个孩子Bob,而后者又有一个孩子Charlie。这一系列的父母和孩子可能继续生活10个人。事先不知道Alice有多少孩子,如何在查询中返回所有这些孩子?我目前正在这样做:

 using (var ctx = new PersonContext())
{
    var result = ctx.People
          .Include(x => x.Parent)
          .Include(x => x.Children)
          .FirstOrDefault();
    return result;
}

但这似乎无法加载Charlie。使用ctx.Configuration.ProxyCreationEnabled = false;似乎没有什么区别。

3 个答案:

答案 0 :(得分:2)

除非您确切知道孩子的数量,否则无法载入孙子女。所以你要么懒得加载它们,要么你可以递归显式地加载它们......比如:

private void LoadChildren(DbContext context, Person person)
{
  var childCollection = context.Entry(person).Collection(x => x.Children);
  if(!childCollection.IsLoaded)
  {
    childCollection.Load();
    foreach(var child in person.Children)
      LoadChildren(context, child);
  }
}
/* ... */
using (var ctx = new PersonContext())
{
    var result = ctx.People
          .Include(x => x.Parent)
          .FirstOrDefault();
    LoadChildren(ctx, result);
    return result;
}

如果您对近似值(具有“最大”量的大孩子)感到满意,我认为您应该能够使用Include的字符串格式执行此操作(完全虽然未经测试,只是发布了这个给你实验):

/* ... */
var numOfGrandChildren = 30; // 30 maximum grandchildren
string childInclude = "";
for(var i = 0; i < numOfChildren; i++)
{
   if(childInclude != "") childInclude+=".";
   childInclude+="Children";
}
using (var ctx = new PersonContext())
{
    var result = ctx.People
          .Include(x => x.Parent)
          .Include(childInclude)
          .FirstOrDefault();
    return result;
}

答案 1 :(得分:1)

您可以通过将导航属性设置为非虚拟来禁用延迟加载: https://msdn.microsoft.com/en-au/data/jj574232.aspx#lazyOffProperty

所以你的课程将是:

public class Person
{
    public string Name { get; set; }
    public Person Parent { get; set; }
    public ICollection<Person> Children { get; set; }
} 

您可以通过配置禁用整个上下文的延迟加载: https://msdn.microsoft.com/en-au/data/jj574232.aspx#lazyOff

public class YourContext : DbContext 
{ 
    public YourContext() 
    { 
        this.Configuration.LazyLoadingEnabled = false; 
    } 
}

答案 2 :(得分:0)

试试这段代码

首先让所有人获得你想要的人。

using (var ctx = new PersonContext())
{
    var people = ctx.People.ToList();
    var result = People.Where(P=>P.Name == "Alice").FirstOrDefault();
    return result;
}