private StrongReferenceContainer RegisterPrefetch(IEnumerable <Key> keys, IHasNestedNodes fieldContainer, Guid enumerationId) { var container = new StrongReferenceContainer(null); TypeInfo modelType = null; if (fieldContainer is ReferenceNode refNode) { modelType = refNode.ReferenceType; } foreach (var key in keys) { var type = key.HasExactType || modelType == null ? key.TypeReference.Type : modelType; if (!key.HasExactType && !type.IsLeaf) { unknownTypeQueue.Enqueue(key); } var cacheKey = new Pair <IHasNestedNodes, TypeInfo>(fieldContainer, type); if (!fieldDescriptorCache.TryGetValue(cacheKey, out var fieldDescriptors)) { fieldDescriptors = PrefetchHelper .GetCachedDescriptorsForFieldsLoadedByDefault(session.Domain, type) .Concat(fieldContainer.NestedNodes.Select(fn => new PrefetchFieldDescriptor(fn.Field, false, true, enumerationId))) .ToList(); fieldDescriptorCache.Add(cacheKey, fieldDescriptors); } _ = container.JoinIfPossible(sessionHandler.Prefetch(key, type, fieldDescriptors)); } var nestedContainers = fieldContainer.NestedNodes.OfType <IHasNestedNodes>(); foreach (var nestedContainer in nestedContainers) { prefetchQueue.Enqueue(new Pair <IEnumerable <Key>, IHasNestedNodes>(keys, nestedContainer)); } return(container); }
public async IAsyncEnumerator <TItem> GetAsyncEnumerator(CancellationToken token = default) { var currentTaskCount = sessionHandler.PrefetchTaskExecutionCount; var aggregatedNodes = NodeAggregator <TItem> .Aggregate(nodes); var resultQueue = new Queue <TItem>(); strongReferenceContainer = new StrongReferenceContainer(null); var enumerationIdentifier = Guid.NewGuid(); async IAsyncEnumerable <TItem> ProcessItem(TItem item1) { resultQueue.Enqueue(item1); if (item1 != null) { foreach (var extractorNode in aggregatedNodes) { var fetchedItems = await RegisterPrefetchAsync(extractorNode.ExtractKeys(item1), extractorNode, enumerationIdentifier, token).ConfigureAwait(false); _ = strongReferenceContainer.JoinIfPossible(fetchedItems); } } if (currentTaskCount == sessionHandler.PrefetchTaskExecutionCount) { yield break; } while (strongReferenceContainer.JoinIfPossible( await sessionHandler.ExecutePrefetchTasksAsync(token).ConfigureAwait(false))) { _ = strongReferenceContainer.JoinIfPossible(await ProcessFetchedElementsAsync(enumerationIdentifier, token).ConfigureAwait(false)); } while (resultQueue.TryDequeue(out var resultItem)) { yield return(resultItem); } currentTaskCount = sessionHandler.PrefetchTaskExecutionCount; } if (source is IAsyncEnumerable <TItem> asyncItemSource) { await foreach (var item in asyncItemSource.WithCancellation(token).ConfigureAwait(false)) { await foreach (var p in ProcessItem(item).WithCancellation(token).ConfigureAwait(false)) { yield return(p); } } } else { var items = source is IQueryable <TItem> queryableSource ? await queryableSource.ExecuteAsync(token).ConfigureAwait(false) : source; foreach (var item in items) { await foreach (var p in ProcessItem(item).WithCancellation(token).ConfigureAwait(false)) { yield return(p); } } } while (strongReferenceContainer.JoinIfPossible( await sessionHandler.ExecutePrefetchTasksAsync(token).ConfigureAwait(false))) { _ = strongReferenceContainer.JoinIfPossible(await ProcessFetchedElementsAsync(enumerationIdentifier, token).ConfigureAwait(false)); } while (resultQueue.TryDequeue(out var resultItem)) { yield return(resultItem); } }
private async ValueTask <StrongReferenceContainer> Prefetch( Key key, TypeInfo type, IList <PrefetchFieldDescriptor> descriptors, bool isAsync, CancellationToken token) { ArgumentValidator.EnsureArgumentNotNull(key, nameof(key)); ArgumentValidator.EnsureArgumentNotNull(descriptors, nameof(descriptors)); if (descriptors.Count == 0) { return(null); } try { EnsureKeyTypeCorrespondsToSpecifiedType(key, type); var currentKey = key; if (!TryGetTupleOfNonRemovedEntity(ref currentKey, out var ownerState)) { return(null); } var selectedFields = descriptors; var currentType = type; var isKeyTypeExact = currentKey.HasExactType || currentKey.TypeReference.Type.IsLeaf || currentKey.TypeReference.Type == type; if (isKeyTypeExact) { currentType = currentKey.TypeReference.Type; EnsureAllFieldsBelongToSpecifiedType(descriptors, currentType); } else { ArgumentValidator.EnsureArgumentNotNull(currentType, "type"); EnsureAllFieldsBelongToSpecifiedType(descriptors, currentType); _ = SetUpContainers(currentKey, currentKey.TypeReference.Type, PrefetchHelper.GetCachedDescriptorsForFieldsLoadedByDefault(session.Domain, currentKey.TypeReference.Type), true, ownerState, true); var hierarchyRoot = currentKey.TypeReference.Type; selectedFields = descriptors .Where(descriptor => descriptor.Field.DeclaringType != hierarchyRoot) .ToList(); } _ = SetUpContainers(currentKey, currentType, selectedFields, isKeyTypeExact, ownerState, ReferenceEquals(descriptors, selectedFields)); StrongReferenceContainer container = null; if (graphContainers.Count >= MaxContainerCount) { container = await ExecuteTasks(false, isAsync, token).ConfigureAwait(false); } if (referenceContainer != null) { _ = referenceContainer.JoinIfPossible(container); return(referenceContainer); } return(container); } catch { CancelTasks(); throw; } }
public async IAsyncEnumerator <T> GetAsyncEnumerator(CancellationToken token = default) { session.Domain.Model.Types.TryGetValue(typeof(T), out var modelType); var taskCount = session.Handler.PrefetchTaskExecutionCount; var container = new StrongReferenceContainer(null); var resultQueue = new Queue <Key>(); var unknownTypeQueue = new Queue <Key>(); using var se = source.GetEnumerator(); bool exists; do { exists = se.MoveNext(); if (exists) { var key = se.Current; var type = key.HasExactType || modelType == null ? key.TypeReference.Type : modelType; if (!key.HasExactType && !type.IsLeaf) { unknownTypeQueue.Enqueue(key); } resultQueue.Enqueue(key); var defaultDescriptors = PrefetchHelper.GetCachedDescriptorsForFieldsLoadedByDefault(session.Domain, type); container.JoinIfPossible( await session.Handler.PrefetchAsync(key, type, defaultDescriptors, token).ConfigureAwait(false)); } if (exists && taskCount == session.Handler.PrefetchTaskExecutionCount) { continue; } if (!exists) { container.JoinIfPossible( await session.Handler.ExecutePrefetchTasksAsync(token).ConfigureAwait(false)); } if (unknownTypeQueue.Count > 0) { while (unknownTypeQueue.Count > 0) { var unknownKey = unknownTypeQueue.Dequeue(); var unknownType = session.EntityStateCache[unknownKey, false].Type; var unknownDescriptors = PrefetchHelper.GetCachedDescriptorsForFieldsLoadedByDefault(session.Domain, unknownType); await session.Handler.PrefetchAsync( unknownKey, unknownType, unknownDescriptors, token).ConfigureAwait(false); } await session.Handler.ExecutePrefetchTasksAsync(token).ConfigureAwait(false); } while (resultQueue.Count > 0) { yield return((T)(IEntity)session.EntityStateCache[resultQueue.Dequeue(), true].Entity); } taskCount = session.Handler.PrefetchTaskExecutionCount; } while (exists); }