예제 #1
0
        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);
        }
예제 #2
0
        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));
            }
        }
예제 #3
0
        /// <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));
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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));
        }