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); } } }
private static Task <object> LoadEntityAsync(Type entityType, object id, ConfiguredSessionProvider sessionProvider, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <object>(cancellationToken)); } try { var session = sessionProvider.GetSession(entityType); return(session.LoadAsync(entityType, id, cancellationToken)); } catch (Exception ex) { return(Task.FromException <object>(ex)); } }
private async Task RefreshFromSessionAsync(Dictionary <Type, List <EntityInfo> > saveMap, ConfiguredSessionProvider sessionProvider, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); foreach (var pair in saveMap) { var modelConfiguration = _breezeConfigurator.GetModelConfiguration(pair.Key); if (modelConfiguration.RefreshAfterSave != true && modelConfiguration.RefreshAfterUpdate != true) { continue; } var session = sessionProvider.GetSession(pair.Key); foreach (var entityInfo in pair.Value) { if (entityInfo.EntityState == EntityState.Added && modelConfiguration.RefreshAfterSave == true || entityInfo.EntityState == EntityState.Modified && modelConfiguration.RefreshAfterUpdate == true) { await(session.RefreshAsync(entityInfo.Entity, cancellationToken)).ConfigureAwait(false); } } } }
private async Task SetupDatabaseEntitiesAsync(Type entityType, List <EntityInfo> entitiesInfo, Dictionary <Type, List <EntityInfo> > saveMap, EntityIdMap entitiesIdMap, ConfiguredSessionProvider sessionProvider, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); var modelConfiguration = _breezeConfigurator.GetModelConfiguration(entityType); var metadata = _entityMetadataProvider.GetMetadata(entityType); if (metadata.ManyToOneIdentifierProperties.Count > 0) { await(SetupManyToOneIdentifierPropertiesAsync(entitiesInfo, saveMap, true, sessionProvider, cancellationToken)).ConfigureAwait(false); } var session = sessionProvider.GetSession(entityType); var batchSize = modelConfiguration.BatchFetchSize ?? session.GetSessionImplementation().Factory.Settings.DefaultBatchFetchSize; var persister = metadata.EntityPersister; var existingIds = entitiesInfo.Where(o => o.EntityState != EntityState.Added) .Select(o => persister.GetIdentifier(o.ClientEntity)) .ToList(); var batchFetcher = metadata.BatchFetcher; var dbEntities = existingIds.Count > 0 ? await(batchFetcher.BatchFetchAsync(session, existingIds, batchSize, cancellationToken)).ConfigureAwait(false) : null; var idMap = entitiesIdMap.GetTypeIdMap(entityType, entitiesInfo.Count); foreach (var entityInfo in entitiesInfo) { foreach (var identifierPropertyName in metadata.IdentifierPropertyNames) { if (entityInfo.OriginalValuesMap.ContainsKey(identifierPropertyName)) { var errors = new[] { new EntityError { EntityTypeName = entityInfo.EntityType.FullName, ErrorMessage = "Cannot update part of the entity's key", ErrorName = "KeyUpdateException", KeyValues = entityInfo.GetIdentifierValues(), PropertyName = identifierPropertyName } }; throw new EntityErrorsException("Cannot update part of the entity's key", errors); } } var id = persister.GetIdentifier(entityInfo.ClientEntity); object dbEntity; if (entityInfo.EntityState == EntityState.Added) { dbEntity = metadata.CreateInstance(); if (metadata.AutoGeneratedKeyType != AutoGeneratedKeyType.Identity && !(persister.IdentifierGenerator is ForeignGenerator)) { if (metadata.ManyToOneIdentifierProperties.Count > 0) { await(SetManyToOneIdentifierAsync(entityInfo, dbEntity, saveMap, false, sessionProvider, cancellationToken)).ConfigureAwait(false); } else { persister.SetIdentifier(dbEntity, id); } } } else if (dbEntities == null || !dbEntities.TryGetValue(id, out dbEntity) || dbEntity == null) { throw new InvalidOperationException($"Entity {entityType} with id {id} was not found."); } entityInfo.Entity = dbEntity; idMap.Add(id, entityInfo); entitiesIdMap.AddToDerivedTypes(entityInfo, id, entitiesInfo.Count); } }