Example #1
0
        public StrongReferenceContainer Prefetch(Key key, TypeInfo type, IList <PrefetchFieldDescriptor> descriptors)
        {
            ArgumentValidator.EnsureArgumentNotNull(key, "key");
            ArgumentValidator.EnsureArgumentNotNull(descriptors, "fields");
            if (descriptors.Count == 0)
            {
                return(null);
            }

            try {
                EnsureKeyTypeCorrespondsToSpecifiedType(key, type);

                EntityState ownerState;
                var         currentKey = key;
                if (!TryGetTupleOfNonRemovedEntity(ref currentKey, out ownerState))
                {
                    return(null);
                }
                var selectedFields = descriptors;
                var currentType    = type;
                StrongReferenceContainer hierarchyRootContainer = null;
                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 = ExecuteTasks();
                }
                if (referenceContainer != null)
                {
                    referenceContainer.JoinIfPossible(container);
                    return(referenceContainer);
                }
                return(container);
            }
            catch {
                CancelTasks();
                throw;
            }
        }
 /// <summary>
 /// Joins this instance with <paramref name="other"/>.
 /// </summary>
 /// <param name="other">The other container.</param>
 public bool Join(StrongReferenceContainer other)
 {
     if (other == null)
     {
         return(false);
     }
     if (!IsRoot)
     {
         root.Join(other);
         return(true);
     }
     if (!other.IsRoot)
     {
         throw new InvalidOperationException();
     }
     other.root = this;
     if (lastJoinedContainer == null)
     {
         nextJoinedContainer = other;
     }
     else if (lastJoinedContainer.nextJoinedContainer != null)
     {
         throw new InvalidOperationException();
     }
     else
     {
         lastJoinedContainer.nextJoinedContainer = other;
     }
     lastJoinedContainer = other.lastJoinedContainer ?? other;
     return(true);
 }
 public void SaveStrongReference(EntityState reference)
 {
     if (referenceContainer == null)
     {
         referenceContainer = new StrongReferenceContainer(null);
     }
     _ = referenceContainer.Join(new StrongReferenceContainer(reference));
 }
        public IEnumerator <T> GetEnumerator()
        {
            TypeInfo modelType;

            session.Domain.Model.Types.TryGetValue(typeof(T), out modelType);
            var  taskCount        = session.Handler.PrefetchTaskExecutionCount;
            var  container        = new StrongReferenceContainer(null);
            var  fieldDescriptors = new List <PrefetchFieldDescriptor>();
            var  resultQueue      = new Queue <Key>();
            var  unknownTypeQueue = new Queue <Key>();
            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(session.Handler.Prefetch(key, type, defaultDescriptors));
                }
                if (exists && taskCount == session.Handler.PrefetchTaskExecutionCount)
                {
                    continue;
                }

                if (!exists)
                {
                    container.JoinIfPossible(session.Handler.ExecutePrefetchTasks());
                }
                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);
                        session.Handler.Prefetch(unknownKey, unknownType, unknownDescriptors);
                    }
                    session.Handler.ExecutePrefetchTasks();
                }
                while (resultQueue.Count > 0)
                {
                    yield return((T)(IEntity)session.EntityStateCache[resultQueue.Dequeue(), true].Entity);
                }
                taskCount = session.Handler.PrefetchTaskExecutionCount;
            } while (exists);
        }
 /// <summary>
 /// Joins this instance with <paramref name="other"/>,
 /// if <paramref name="other"/> is not <see langword="null" /> and is the root of other containers' chain.
 /// </summary>
 /// <param name="other">The other container.</param>
 public bool JoinIfPossible(StrongReferenceContainer other)
 {
     if (other == null)
     {
         return(false);
     }
     if (other.IsRoot)
     {
         Join(other);
     }
     return(true);
 }
        public IEnumerator <TItem> GetEnumerator()
        {
            var currentTaskCount = sessionHandler.PrefetchTaskExecutionCount;
            var aggregatedNodes  = NodeAggregator <TItem> .Aggregate(nodes);

            var resultQueue = new Queue <TItem>();
            var container   = new StrongReferenceContainer(null);

            foreach (var item in source)
            {
                resultQueue.Enqueue(item);
                if (item != null)
                {
                    foreach (var extractorNode in aggregatedNodes)
                    {
                        container.JoinIfPossible(RegisterPrefetch(extractorNode.ExtractKeys(item), extractorNode));
                    }
                }

                if (currentTaskCount == sessionHandler.PrefetchTaskExecutionCount)
                {
                    continue;
                }

                while (container.JoinIfPossible(sessionHandler.ExecutePrefetchTasks()))
                {
                    container.JoinIfPossible(ProcessFetchedElements());
                }

                while (resultQueue.TryDequeue(out var resultItem))
                {
                    yield return(resultItem);
                }

                currentTaskCount = sessionHandler.PrefetchTaskExecutionCount;
            }

            while (container.JoinIfPossible(sessionHandler.ExecutePrefetchTasks()))
            {
                container.JoinIfPossible(ProcessFetchedElements());
            }

            while (resultQueue.TryDequeue(out var resultItem))
            {
                yield return(resultItem);
            }
        }
        private async Task <StrongReferenceContainer> RegisterPrefetchAsync(IReadOnlyCollection <Key> keys,
                                                                            IHasNestedNodes fieldContainer, Guid enumerationId, CancellationToken token)
        {
            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(
                    await sessionHandler.PrefetchAsync(key, type, fieldDescriptors, token).ConfigureAwait(false));
            }

            var nestedContainers = fieldContainer.NestedNodes.OfType <IHasNestedNodes>();

            foreach (var nestedContainer in nestedContainers)
            {
                prefetchQueue.Enqueue(new Pair <IEnumerable <Key>, IHasNestedNodes>(keys, nestedContainer));
            }

            return(container);
        }
Example #8
0
 public StrongReferenceContainer ExecuteTasks(bool skipPersist)
 {
     if (graphContainers.Count == 0)
     {
         referenceContainer = null;
         return(null);
     }
     try {
         var batchExecuted = fetcher.ExecuteTasks(graphContainers, skipPersist);
         TaskExecutionCount += batchExecuted;
         foreach (var graphContainer in graphContainers)
         {
             graphContainer.NotifyAboutExtractionOfKeysWithUnknownType();
         }
         return(referenceContainer);
     }
     finally {
         CancelTasks();
     }
 }
        private async ValueTask <StrongReferenceContainer> ExecuteTasks(bool skipPersist, bool isAsync, CancellationToken token)
        {
            if (graphContainers.Count == 0)
            {
                referenceContainer = null;
                return(null);
            }
            try {
                var batchExecuted =
                    await fetcher.ExecuteTasks(graphContainers, skipPersist, isAsync, token).ConfigureAwait(false);

                TaskExecutionCount += batchExecuted;
                foreach (var graphContainer in graphContainers)
                {
                    graphContainer.NotifyAboutExtractionOfKeysWithUnknownType();
                }
                return(referenceContainer);
            }
            finally {
                CancelTasks();
            }
        }
        private StrongReferenceContainer RegisterPrefetch(IEnumerable <Key> keys, IHasNestedNodes fieldContainer)
        {
            var      container = new StrongReferenceContainer(null);
            TypeInfo modelType = null;
            var      refNode   = fieldContainer as ReferenceNode;

            if (refNode != null)
            {
                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);
                }
                IList <PrefetchFieldDescriptor> fieldDescriptors;
                var cacheKey = new Pair <IHasNestedNodes, TypeInfo>(fieldContainer, type);
                if (!fieldDescriptorCache.TryGetValue(cacheKey, out fieldDescriptors))
                {
                    fieldDescriptors = PrefetchHelper
                                       .GetCachedDescriptorsForFieldsLoadedByDefault(session.Domain, type)
                                       .Concat(fieldContainer.NestedNodes.Select(fn => new PrefetchFieldDescriptor(fn.Field, false, true))).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);
        }
        private async Task <StrongReferenceContainer> ProcessFetchedElementsAsync(Guid enumerationId, CancellationToken token)
        {
            var container = new StrongReferenceContainer(null);

            while (unknownTypeQueue.TryDequeue(out var unknownKey))
            {
                var unknownType        = session.EntityStateCache[unknownKey, false].Type;
                var unknownDescriptors =
                    PrefetchHelper.GetCachedDescriptorsForFieldsLoadedByDefault(session.Domain, unknownType);
                _ = await sessionHandler.PrefetchAsync(unknownKey, unknownType, unknownDescriptors, token).ConfigureAwait(false);
            }

            while (prefetchQueue.TryDequeue(out var pair))
            {
                var parentKeys  = pair.First;
                var nestedNodes = pair.Second;
                var keys        = new List <Key>();
                foreach (var parentKey in parentKeys)
                {
                    var entityState = session.EntityStateCache[parentKey, false];
                    if (entityState == null)
                    {
                        _           = container.JoinIfPossible(await sessionHandler.ExecutePrefetchTasksAsync(true, token).ConfigureAwait(false));
                        entityState = session.EntityStateCache[parentKey, false];
                        if (entityState == null)
                        {
                            throw new InvalidOperationException(string.Format(Strings.ExCannotResolveEntityWithKeyX, parentKey));
                        }
                    }

                    keys.AddRange(nestedNodes.ExtractKeys(entityState.Entity));
                }

                _ = container.JoinIfPossible(await RegisterPrefetchAsync(keys, nestedNodes, enumerationId, token).ConfigureAwait(false));
            }

            return(container);
        }
        private StrongReferenceContainer ProcessFetchedElements()
        {
            var container = new StrongReferenceContainer(null);

            taskCount = sessionHandler.PrefetchTaskExecutionCount;
            while (unknownTypeQueue.Count > 0)
            {
                var unknownKey         = unknownTypeQueue.Dequeue();
                var unknownType        = session.EntityStateCache[unknownKey, false].Type;
                var unknownDescriptors = PrefetchHelper.GetCachedDescriptorsForFieldsLoadedByDefault(session.Domain, unknownType);
                sessionHandler.Prefetch(unknownKey, unknownType, unknownDescriptors);
            }
            while (prefetchQueue.Count > 0)
            {
                var pair        = prefetchQueue.Dequeue();
                var parentKeys  = pair.First;
                var nestedNodes = pair.Second;
                var keys        = new List <Key>();
                foreach (var parentKey in parentKeys)
                {
                    var entityState = session.EntityStateCache[parentKey, false];
                    if (entityState == null)
                    {
                        container.JoinIfPossible(sessionHandler.ExecutePrefetchTasks(true));
                        taskCount   = sessionHandler.PrefetchTaskExecutionCount;
                        entityState = session.EntityStateCache[parentKey, false];
                        if (entityState == null)
                        {
                            throw new InvalidOperationException(string.Format(Strings.ExCannotResolveEntityWithKeyX, parentKey));
                        }
                    }
                    keys.AddRange(nestedNodes.ExtractKeys(entityState.Entity));
                }
                container.JoinIfPossible(RegisterPrefetch(keys, nestedNodes));
            }
            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);
            }
        }
 public void CancelTasks()
 {
     referenceContainer = null;
     graphContainers.Clear();
 }
Example #15
0
        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);
        }