private async Task UpdateEntityAssociationAsync( EntityAssociation association, EntityInfo entityInfo, AbstractEntityPersister persister, EntityIdMap entitiesIdMap, DependencyGraph dependencyGraph, ConfiguredSessionProvider sessionProvider, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); var dbEntity = entityInfo.Entity; var originalFkValue = await(GetClientForeignKeyValueAsync(association, entityInfo, entitiesIdMap, true, sessionProvider, cancellationToken)).ConfigureAwait(false); TryAddToGraphAndUpdateParent(entityInfo, entitiesIdMap, dependencyGraph, originalFkValue, association, true, true, sessionProvider, out _); var newFkValue = await(GetClientForeignKeyValueAsync(association, entityInfo, entitiesIdMap, false, sessionProvider, cancellationToken)).ConfigureAwait(false); TryAddToGraphAndUpdateParent(entityInfo, entitiesIdMap, dependencyGraph, newFkValue, association, false, true, sessionProvider, out var parentEntityInfo); // Set the entity association (e.g. Order = value) var associatedEntity = newFkValue != null ? parentEntityInfo?.Entity ?? await(LoadEntityAsync(association.EntityType, newFkValue, sessionProvider, cancellationToken)).ConfigureAwait(false) : null; persister.SetPropertyValue( dbEntity, persister.GetPropertyIndex(association.AssociationPropertyName), associatedEntity); }
private Task <object> GetClientForeignKeyValueAsync( EntityAssociation association, EntityInfo entityInfo, EntityIdMap entitiesIdMap, bool original, ConfiguredSessionProvider sessionProvider, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <object>(cancellationToken)); } try { var metadata = entityInfo.EntityMetadata; if (association.IsOneToOne) { // TODO: verify this block if (original) { return(entityInfo.OriginalValuesMap != null && entityInfo.OriginalValuesMap.TryGetValue(metadata.EntityPersister.IdentifierPropertyName, out var originalValue) ? Task.FromResult <object>(ConvertToType(originalValue, association.IdentifierType.ReturnedClass) ) : Task.FromResult <object>(null)); } return(Task.FromResult <object>(metadata.EntityPersister.GetIdentifier(entityInfo.ClientEntity))); } var fkProperties = association.ForeignKeyPropertyNames; if (association.IdentifierType is ComponentType idComponentType) { return(GetClientCompositeKeyValueAsync(association, idComponentType, entityInfo, metadata, entitiesIdMap, original, sessionProvider, cancellationToken)); } var fkPropertyName = fkProperties[0]; if (original) { return(entityInfo.OriginalValuesMap != null && entityInfo.OriginalValuesMap.TryGetValue(fkPropertyName, out var originalValue) ? Task.FromResult <object>(ConvertToType(originalValue, association.IdentifierType.ReturnedClass) ) : Task.FromResult <object>(null)); } if (metadata.SyntheticForeignKeyProperties.ContainsKey(fkPropertyName)) { // The unmapped property may be ignored from metadata return(entityInfo.UnmappedValuesMap != null && entityInfo.UnmappedValuesMap.TryGetValue(fkPropertyName, out var value) ? Task.FromResult <object>(ConvertToType(value, association.IdentifierType.ReturnedClass) ) : Task.FromResult <object>(null)); } var persister = metadata.EntityPersister; return(Task.FromResult <object>(persister.GetPropertyValue(entityInfo.ClientEntity, persister.GetPropertyIndex(fkPropertyName)))); } catch (Exception ex) { return(Task.FromException <object>(ex)); } }
/// <summary> /// Tries to add a child and its parent <see cref="EntityInfo"/> to the graph. /// </summary> /// <param name="child">The child entity info.</param> /// <param name="parent">The parent entity info.</param> /// <param name="association">The association between the parent and its child.</param> /// <returns>Whether the child and its parent were added to the graph.</returns> public bool TryAddToGraph(EntityInfo child, EntityInfo parent, EntityAssociation association) { var childNode = GetOrAdd(child); if (parent == null) { return(false); } var parentNode = GetOrAdd(parent); return(parentNode.AddChild(childNode, association) && childNode.AddParent(parentNode, association)); }
internal bool AddChild(GraphNode child, EntityAssociation association) { if (_children == null) { _children = new Dictionary <GraphNode, EntityAssociation>(); } if (_children.ContainsKey(child)) { return(false); } _children.Add(child, association); return(true); }
internal bool AddParent(GraphNode parent, EntityAssociation association) { if (_parents == null) { _parents = new Dictionary <GraphNode, EntityAssociation>(); } if (_parents.ContainsKey(parent)) { return(false); } _parents.Add(parent, association); return(true); }
private async Task <object> GetClientCompositeKeyValueAsync( EntityAssociation association, ComponentType idComponentType, EntityInfo entityInfo, EntityMetadata metadata, EntityIdMap entitiesIdMap, bool original, ConfiguredSessionProvider sessionProvider, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); var persister = metadata.EntityPersister; var types = idComponentType.Subtypes; var relatedMetadata = _entityMetadataProvider.GetMetadata(association.EntityType); var values = new object[types.Length]; var fkIndex = 0; var counter = 0; for (var i = 0; i < types.Length; i++) { var type = types[i]; var columnSpan = type.GetColumnSpan(persister.Factory); var propertyValues = new object[columnSpan]; for (var j = 0; j < columnSpan; j++) { var fkProperty = association.ForeignKeyPropertyNames[fkIndex]; if (original && entityInfo.OriginalValuesMap != null && entityInfo.OriginalValuesMap.TryGetValue(fkProperty, out var originalValue)) { propertyValues[j] = ConvertToType(originalValue, relatedMetadata.IdentifierPropertyTypes[fkIndex]); counter++; } else if (metadata.SyntheticForeignKeyProperties.ContainsKey(fkProperty)) { if (entityInfo.UnmappedValuesMap == null || !entityInfo.UnmappedValuesMap.TryGetValue(fkProperty, out var fkValue)) { throw new InvalidOperationException($"Unable to retrieve the synthetic property '{fkProperty}' value for type {entityInfo.EntityType} from {nameof(EntityInfo.UnmappedValuesMap)}."); } propertyValues[j] = ConvertToType(fkValue, relatedMetadata.IdentifierPropertyTypes[fkIndex]); } else { propertyValues[j] = persister.GetPropertyValue(entityInfo.ClientEntity, persister.GetPropertyIndex(fkProperty)); } fkIndex++; } if (type.IsAssociationType && type is EntityType entityType) { var relatedPersister = (IEntityPersister)entityType.GetAssociatedJoinable(persister.Factory); object propertyKey; if (relatedPersister.IdentifierType is ComponentType componentType) { // TODO: add support for a relation to another key-many-to-one propertyKey = componentType.Instantiate(); componentType.SetPropertyValues(propertyKey, propertyValues); } else { propertyKey = propertyValues[0]; } if (entitiesIdMap.TryGetValue(relatedPersister.MappedClass, out var idMap) && idMap.TryGetValue(propertyKey, out var relatedEntityInfo)) { values[i] = relatedEntityInfo.Entity; } else { values[i] = await(LoadEntityAsync(relatedPersister.MappedClass, propertyKey, sessionProvider, cancellationToken)).ConfigureAwait(false); } } else { values[i] = propertyValues[0]; } } if (original && counter == 0) { return(null); // The key was not changed } var key = idComponentType.Instantiate(); idComponentType.SetPropertyValues(key, values); return(key); }
private static bool DoCascade(CascadingAction cascadingAction, GraphNode childNode, EntityAssociation childAssociation) { var cascade = childAssociation.InverseAssociationPropertyCascadeStyle; if (cascade == null) { return(false); } return(cascade.DoCascade(cascadingAction) && DoCascade(cascadingAction, childNode.EntityInfo.EntityState)); }