我的模型Category
具有自引用关系:
public class Category
{
public Category()
{
this.Childs = new HashSet<Category>();
}
public int CategoryId { get; set; }
public int? ParentId { get; set; }
public virtual Category Parent { get; set; }
public HashSet<Category> Childs { get; set; }
//... other useless properties
}
关系配置在上下文中定义:
modelBuilder.Entity<Category>()
.HasOptional(c => c.Parent)
.WithMany(c => c.Childs)
.HasForeignKey(m => m.ParentId);
我还包括通用Repository
,其中包含方法:
public IEnumerable<T> GetAll()
{
return this.dbSet.ToList();
}
public IQueryable<T> AsQuerable()
{
return this.dbSet.AsQueryable();
}
现在发生了非常奇怪的行为。我称之为方法:
var categoriesEntites =
this.catogries.AsQuerable()
.Where(cat => cat.ProjectId == projectId
&& cat.ParentId == null)
.ToList();
// this.categories is of type `Repository<Category>`
在结果中,Childs
未加载..:
但是我之前打电话给GetAll
:
this.catogries.GetAll();
var categoriesEntites =
this.catogries.AsQuerable()
.Where(cat => cat.ProjectId == projectId
&& cat.ParentId == null)
.ToList();
突然导航属性有效..
之前我曾经多次使用这种方法,而且我从未遇到过这样的问题。
一些想法? LazyLoading
当然已开启..
为了让事情变得更奇怪,我还有其他自引用实体(以完全相同的方式构建)并且没有这样的错误。
顺便说一句。对不起有关导航属性中的拼写错误,当然应该是Children
,而不是Childs
...
答案 0 :(得分:1)
当您在ToList()
方法中执行GetAll()
时,EF会加载整个表格并在本地存储这些实体。这就是执行此查询时它们似乎已加载的原因:
var categoriesEntites =
this.catogries.AsQuerable()
.Where(cat => cat.ParentId == null)
.ToList();
如果查看上面查询生成的SQL,它实际上只获取ParentId
为空的类别:
SELECT
[Extent1].[CategoryId] AS [CategoryId],
[Extent1].[ParentId] AS [ParentId]
FROM [dbo].[Categories] AS [Extent1]
WHERE [Extent1].[ParentId] IS NULL
即使在VS调试器中检查集合(触发延迟加载)之后,也不会获取子集合,因为它已经由EF本地加载和存储。
如果您想在不使用ToList()
(或GetAll()
)的情况下获取子对象,请在您的子集合中使用virtual
关键字。这是延迟加载的要求,将在代码或VS调试器访问该子集合时获取。
public virtual HashSet<Category> Childs { get; set; }