private SaveResult CreateSaveResultFromValues()

in src/Epam.GraphQL/Loaders/MutableLoader.cs [136:219]


        private SaveResult<TEntity, TId, TExecutionContext> CreateSaveResultFromValues(string fieldName, IEnumerable<InputItem<TEntity>> entities) => new(
            pendingItems: entities
                .Select(entity =>
                    new SaveResultItem<TEntity, TId>(
                        getId: GetId,
                        payload: entity.Payload,
                        isNew: IsFakeId(GetId(entity.Payload)),
                        properties: entity.Properties))
                .ToList(),
            processedItems: new List<SaveResultItem<TEntity?, TId>>(),
            postponedItems: new List<SaveResultItem<TEntity, TId>>(),
            loader: this,
            fieldName: fieldName);

        private SaveResult<TEntity, TId, TExecutionContext> CreateSaveResultFromValues(string fieldName, IEnumerable<TEntity> entities) => new(
            processedItems: entities
                .Select(entity =>
                    new SaveResultItem<TEntity?, TId>(
                        getId: e => GetId(e ?? throw new NotSupportedException()),
                        payload: entity,
                        isNew: EqualityComparer<TId?>.Default.Equals(GetId(entity), default),
                        properties: new Dictionary<string, object?>()))
                .ToList(),
            pendingItems: new List<SaveResultItem<TEntity, TId>>(),
            postponedItems: new List<SaveResultItem<TEntity, TId>>(),
            loader: this,
            fieldName: fieldName);

        private async Task<IEnumerable<ISaveResult<TExecutionContext>>> MutateAsync(IResolveFieldContext context, SaveResult<TEntity, TId, TExecutionContext> previousSaveResult)
        {
            var profiler = context.GetProfiler();

            using (profiler.Step($"{GetType().HumanizedName()}.{nameof(MutateAsync)}"))
            {
                var dbContext = context.GetDataContext();
                var pendingItems = previousSaveResult.PendingItems;

                if (!pendingItems.Any())
                {
                    return Enumerable.Repeat(previousSaveResult, 1);
                }

                var itemsToCreate = pendingItems
                    .Where(item => item.IsNew && !Registry.HasFakePropertyValues(GetType(), item.Payload, item.Properties));

                await CreateNewItemsAsync(context, profiler, dbContext, itemsToCreate).ConfigureAwait(false);

                var itemsToUpdate = pendingItems
                    .Where(item => !item.IsNew && !Registry.HasFakePropertyValues(GetType(), item.Payload, item.Properties)
                        && !Registry.HasFakePropertyValuesPostponedForSave(item.Payload, item.Properties));

                await UpdateExistingItemsAsync(context, profiler, itemsToUpdate).ConfigureAwait(false);

                using (profiler.Step($"PrepareResult"))
                {
                    var postponedItems = pendingItems
                        .Where(item => Registry.HasFakePropertyValues(GetType(), item.Payload, item.Properties));

                    var postponedForSaveItems =
                        pendingItems
                            .Where(item => !Registry.HasFakePropertyValues(GetType(), item.Payload, item.Properties)
                                && Registry.HasFakePropertyValuesPostponedForSave(item.Payload, item.Properties))
                            .Union(previousSaveResult.PostponedItems);

                    var processedItems = previousSaveResult.ProcessedItems.ToList();
#pragma warning disable CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types.
                    processedItems.AddRange(itemsToCreate);
                    processedItems.AddRange(itemsToUpdate);
#pragma warning restore CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types.

                    var result = new List<ISaveResult<TExecutionContext>>
                    {
                        new SaveResult<TEntity, TId, TExecutionContext>(
                            pendingItems: postponedItems.ToList(),
                            processedItems: processedItems,
                            postponedItems: postponedForSaveItems.ToList(),
                            loader: this,
                            fieldName: previousSaveResult.FieldName),
                    };

                    return result;
                }
            }
        }