我有这个型号:
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;
似乎没有什么区别。
答案 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;
}