Skip to main content
 首页 » 编程设计

c#之您如何急切加载一个实体可能拥有的所有子集合

2024年04月18日32lyj

我有这个模型:

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

我的问题:我如何归还所有 child ,无论他们有多深?例如,我可以有一个人 Alice,他有一个 child Bob,而他又有一个 child Charlie。这条 parent 和 child 的链条可能会持续 10 个以上的 Persons。在事先不知道爱丽丝有多少 child 的情况下,我如何在查询中返回所有 child ?我目前正在这样做:

 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; 似乎也没有什么不同。

请您参考如下方法:

除非您确切知道 child 的数量,否则无法加载孙子。所以你要么延迟加载它们,要么你可以显式地递归加载它们......像这样:

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; 
}