假设我有以下型号:
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.
}
我不想使用延迟加载,因为这会影响性能(而且延迟加载不会异步加载相关实体(。Eager和Explicit加载都很好。
编辑:我主要寻找的是一种检查导航属性是否已完全加载的方法,这样我就可以加载它。
您无法检测是否所有相关实体都经过了实体框架。
所显示的内容之所以有效,是因为dbContext.SubjectResponses.SingleAsync(s => s.Id == 1)
中的实体的SubjectId
为1,并且将被缓存,然后依次附加到dbContext.Subjects.SingleAsync(s => s.Id == 1)
的结果。
EF和您的代码都无法知道所有SubjectId
为1的SubjectResponses
都已从数据库加载,因此您必须显式加载它们:
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);
如果相关实体(或实体集合(尚未加载(包含(,则可能引发异常,请参阅不可为null的属性和初始化。
以下是一对多关系的示例:
class MyEntity
{
// Assume read-only access.
public IReadOnlyList<MyRelatedEntity> MyRelatedEntities =>
_myRelatedEntities?.ToList().AsReadOnly() ??
throw new InvalidOperationException("MyRelatedEntities not loaded.");
private readonly IEnumerable<MyRelatedEntity>? _myRelatedEntities = null;
}
class MyRelatedEntity
{
public MyEntity MyEntity
{
get => _myEntity ??
throw new InvalidOperationException("MyEntity not loaded.");
set => _myEntity = value;
}
private MyEntity? _myEntity = null;
}
实体框架核心将自动设置支持字段,您可以检测相关实体是否已加载。
不幸的是,这种方法不适用于可选的关系,或者至少我还没有弄清楚如何做到这一点