说我有以下模型:
public class Subject
{
private List<SubjectResponse> responses;
public int Id { get; private set; }
public IEnumerable<SubjectResponse> Responses => responses.ToList();
public void Foo()
{
// How do I check here if Responses fully has been loaded?
foreach (var response in Responses)
{
// ...
}
}
}
public class SubjectResponse
{
public int Id { get; private set; }
}
如何检查所有响应是否都已加载到Foo()
中?我可能会检查if (Responses is null)
,但这在所有情况下都行不通。
这是可能做错事的最小示例。在真实的应用程序中,响应可以在完全不同的位置加载。但是h这显示了EF如何固定响应,因此它可以包含条目,但不是所有条目。
public async Task Bar()
{
var response = await dbContext.SubjectResponses.SingleAsync(s => s.Id == 1);
var subject = await dbContext.Subjects.SingleAsync(s => s.Id == 1);
subject.Foo();
// subject.Responses now has a count if 1, when there might actually be more responses.
}
由于性能影响(并且因为惰性加载不会异步加载相关的实体),所以我不想使用延迟加载。渴望和显式加载都可以。
编辑:我主要要寻找的是一种检查导航属性是否已完全加载的方法,以便我可以加载它。
答案 0 :(得分:1)
您无法检测到所有相关实体是否恰好已通过实体框架传递。
您显示的内容之所以有效,是因为dbContext.SubjectResponses.SingleAsync(s => s.Id == 1)
中的实体的SubjectId
为1,将被缓存,并随后附加到dbContext.Subjects.SingleAsync(s => s.Id == 1)
的结果上。
EF和您的代码都无法知道已经从数据库中加载了SubjectResponses
为1的 all SubjectId
,所以您必须explicitly load them:
var subject = await dbContext.Subjects.SingleAsync(s => s.Id == 1);
await dbContext.Entity(subject)
.Reference(s => s.responses)
.LoadAsync();
但是您不能这样做,因为Subject.responses
是私有的,因此您必须在实体的Foo()
方法中执行此操作,并且必须将DbContext注入到您的实体,那将变成一团糟。
为什么不仅要务实地做到这一点,还应事先将Responses
设为公共自动财产,并将Include()
设为相关实体:
var subject = await dbContext.Subjects.Include(s => s.Responses).SingleAsync(s => s.Id == 1);