protected async Task LoadRecursiveAsync<TEntityToLoad>(TEntityToLoad entity, CancellationToken cancellationToken) where TEntityToLoad : class, IEntity
{
// this.Context is of type Microsoft.EntityFrameworkCore.DbContext
EntityEntry<TEntityToLoad> entry = this.Context.Entry(entity);
foreach (NavigationEntry navigationEntry in entry.Navigations.Where(ne => !ne.IsLoaded))
{
cancellationToken.ThrowIfCancellationRequested();
await LoadRecursiveAsyncInternal(navigationEntry);
}
return;
async Task LoadRecursiveAsyncInternal(NavigationEntry navigationEntry)
{
await navigationEntry.LoadAsync(cancellationToken);
object? currentValue = navigationEntry.CurrentValue;
switch (currentValue)
{
case IEntity loadedEntity:
{
foreach (NavigationEntry navigation in this.Context.Entry(loadedEntity).Navigations.Where(ne => !ne.IsLoaded))
{
cancellationToken.ThrowIfCancellationRequested();
await LoadRecursiveAsyncInternal(navigation);
}
break;
}
case null:
break;
default:
{
Type type = currentValue.GetType();
if(!type.IsAssignableTo(typeof(IEnumerable)))
{
return;
}
if (type.GetGenericArguments() is [{ } entityType] && entityType.IsAssignableTo(typeof(IEntity)))
{
foreach (IEntity loadedEntity in (IEnumerable)currentValue)
{
foreach (NavigationEntry navigation in this.Context.Entry(loadedEntity).Navigations.Where(ne => !ne.IsLoaded))
{
cancellationToken.ThrowIfCancellationRequested();
await LoadRecursiveAsyncInternal(navigation);
}
}
}
break;
}
}
}
}