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;
}
}
}