private static async Task ProcessSavesAsync( List <EntityInfo> saveOrder, PersistenceManager persistenceManager, SaveChangesContext context, ISaveChangesOptions saveChangesOptions, ConfiguredSessionProvider sessionProvider, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); foreach (var entityInfo in saveOrder) { await(persistenceManager.BeforeSaveEntityChangesAsync(entityInfo, context, cancellationToken)).ConfigureAwait(false); var beforeSaveEntityChangesTask = saveChangesOptions?.BeforeSaveEntityChangesAsync(entityInfo, context, cancellationToken); if (beforeSaveEntityChangesTask != null) { await(beforeSaveEntityChangesTask).ConfigureAwait(false); } var session = sessionProvider.GetSession(entityInfo.EntityType); try { switch (entityInfo.EntityState) { case EntityState.Modified: await(session.UpdateAsync(entityInfo.Entity, cancellationToken)).ConfigureAwait(false); break; case EntityState.Added: await(session.SaveAsync(entityInfo.Entity, cancellationToken)).ConfigureAwait(false); break; case EntityState.Deleted: await(session.DeleteAsync(entityInfo.Entity, cancellationToken)).ConfigureAwait(false); break; } } catch (PropertyValueException e) { // NH can throw this when a not null property is null or transient (e.g. not-null property references a null or transient value) var errors = new[] { // KeyValues cannot be determined as the exception may reference another entity new EntityError { EntityTypeName = e.EntityName, ErrorMessage = e.Message, ErrorName = "PropertyValueException", PropertyName = e.PropertyName } }; throw new EntityErrorsException(e.Message, errors); } } }
internal async Task <List <KeyMapping> > FetchAndApplyChangesInternalAsync( PersistenceManager persistenceManager, SaveChangesContext context, ISaveChangesOptions saveChangesOptions, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); await(persistenceManager.BeforeFetchEntitiesAsync(context, cancellationToken)).ConfigureAwait(false); var beforeFetchEntitiesTask = saveChangesOptions?.BeforeFetchEntitiesAsync(context, cancellationToken); if (beforeFetchEntitiesTask != null) { await(beforeFetchEntitiesTask).ConfigureAwait(false); } var saveMap = context.SaveMap; using var sessionProvider = new ConfiguredSessionProvider(_sessionProvider); var entitiesIdMap = new EntityIdMap(saveMap.Count); var saveMapList = saveMap.ToList(); // Make sure that entity types that have all key-many-to-one are sorted so that the associated entities will be processed before them saveMapList.Sort(CompareSaveMapTypes); foreach (var pair in saveMapList) { await(SetupDatabaseEntitiesAsync(pair.Key, pair.Value, saveMap, entitiesIdMap, sessionProvider, cancellationToken)).ConfigureAwait(false); } await(persistenceManager.BeforeApplyChangesAsync(context, cancellationToken)).ConfigureAwait(false); var beforeApplyChangesTask = saveChangesOptions?.BeforeApplyChangesAsync(context, cancellationToken); if (beforeApplyChangesTask != null) { await(beforeApplyChangesTask).ConfigureAwait(false); } AddAdditionalEntities(context.AdditionalEntities, context.SaveMap); context.AdditionalEntities?.Clear(); var dependencyGraph = new DependencyGraph(saveMap.Count); foreach (var pair in saveMap) { await(ApplyChangesAsync(pair.Key, pair.Value, dependencyGraph, saveMap, entitiesIdMap, sessionProvider, cancellationToken)).ConfigureAwait(false); } persistenceManager.ValidateDependencyGraph(dependencyGraph, context); saveChangesOptions?.ValidateDependencyGraph(dependencyGraph, context); var saveOrder = dependencyGraph.GetSaveOrder(); await(persistenceManager.BeforeSaveChangesAsync(saveOrder, context, cancellationToken)).ConfigureAwait(false); var beforeSaveChangesTask = saveChangesOptions?.BeforeSaveChangesAsync(saveOrder, context, cancellationToken); if (beforeSaveChangesTask != null) { await(beforeSaveChangesTask).ConfigureAwait(false); } await(ProcessSavesAsync(saveOrder, persistenceManager, context, saveChangesOptions, sessionProvider, cancellationToken)).ConfigureAwait(false); await(persistenceManager.AfterSaveChangesAsync(saveOrder, context, cancellationToken)).ConfigureAwait(false); var afterSaveChangesTask = saveChangesOptions?.AfterSaveChangesAsync(saveOrder, context, cancellationToken); if (afterSaveChangesTask != null) { await(afterSaveChangesTask).ConfigureAwait(false); } await(FlushSessionsAsync(sessionProvider, cancellationToken)).ConfigureAwait(false); await(RefreshFromSessionAsync(saveMap, sessionProvider, cancellationToken)).ConfigureAwait(false); var keyMappings = GetKeyMappings(saveMap).ToList(); await(persistenceManager.AfterFlushChangesAsync(context, keyMappings, cancellationToken)).ConfigureAwait(false); var afterFlushChangesTask = saveChangesOptions?.AfterFlushChangesAsync(context, keyMappings, cancellationToken); if (afterFlushChangesTask != null) { await(afterFlushChangesTask).ConfigureAwait(false); } UpdateClientEntities(context); return(keyMappings); }