示例#1
0
        private static void SetForeignKeyProperties(
            InternalEntityEntry dependentEntry,
            InternalEntityEntry principalEntry,
            IForeignKey foreignKey,
            bool setModified,
            bool fromQuery)
        {
            var principalProperties = foreignKey.PrincipalKey.Properties;
            var dependentProperties = foreignKey.Properties;

            for (var i = 0; i < foreignKey.Properties.Count; i++)
            {
                var principalProperty = principalProperties[i];
                var dependentProperty = dependentProperties[i];
                var principalValue    = principalEntry[principalProperty];
                var dependentValue    = dependentEntry[dependentProperty];

                if (!PrincipalValueEqualsDependentValue(principalProperty, dependentValue, principalValue) ||
                    (dependentEntry.IsConceptualNull(dependentProperty) &&
                     principalValue != null))
                {
                    if (principalEntry.HasTemporaryValue(principalProperty))
                    {
                        dependentEntry.SetTemporaryValue(dependentProperty, principalValue, setModified);
                    }
                    else
                    {
                        dependentEntry.SetProperty(dependentProperty, principalValue, fromQuery, setModified);
                    }

                    dependentEntry.StateManager.UpdateDependentMap(dependentEntry, foreignKey);
                    dependentEntry.SetRelationshipSnapshotValue(dependentProperty, principalValue);
                }
            }
        }
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual async Task <InternalEntityEntry> PropagateValueAsync(
            InternalEntityEntry entry,
            IProperty property,
            CancellationToken cancellationToken = default)
        {
            Check.DebugAssert(property.IsForeignKey(), $"property {property} is not part of an FK");

            var principalEntry = TryPropagateValue(entry, property);

            if (principalEntry == null &&
                property.IsKey())
            {
                var valueGenerator = TryGetValueGenerator(property);

                if (valueGenerator != null)
                {
                    var value = await valueGenerator.NextAsync(new EntityEntry(entry), cancellationToken);

                    if (valueGenerator.GeneratesTemporaryValues)
                    {
                        entry.SetTemporaryValue(property, value);
                    }
                    else
                    {
                        entry[property] = value;
                    }
                }
            }

            return(principalEntry);
        }
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual InternalEntityEntry PropagateValue(InternalEntityEntry entry, IProperty property)
        {
            Check.DebugAssert(property.IsForeignKey(), $"property {property} is not part of an FK");

            var principalEntry = TryPropagateValue(entry, property);

            if (principalEntry == null &&
                property.IsKey())
            {
                var valueGenerator = TryGetValueGenerator(property);

                if (valueGenerator != null)
                {
                    var value = valueGenerator.Next(new EntityEntry(entry));

                    if (valueGenerator.GeneratesTemporaryValues)
                    {
                        entry.SetTemporaryValue(property, value);
                    }
                    else
                    {
                        entry[property] = value;
                    }
                }
            }

            return(principalEntry);
        }
        private static InternalEntityEntry TryPropagateValue(InternalEntityEntry entry, IProperty property)
        {
            var entityType   = entry.EntityType;
            var stateManager = entry.StateManager;

            foreach (var foreignKey in entityType.GetForeignKeys())
            {
                for (var propertyIndex = 0; propertyIndex < foreignKey.Properties.Count; propertyIndex++)
                {
                    if (property == foreignKey.Properties[propertyIndex])
                    {
                        var principal = foreignKey.DependentToPrincipal == null
                            ? null
                            : entry[foreignKey.DependentToPrincipal];
                        InternalEntityEntry principalEntry = null;
                        if (principal != null)
                        {
                            principalEntry = stateManager.GetOrCreateEntry(principal, foreignKey.PrincipalEntityType);
                        }
                        else if (foreignKey.PrincipalToDependent != null)
                        {
                            foreach (var danglerEntry in stateManager.GetRecordedReferrers(entry.Entity, clear: false))
                            {
                                if (danglerEntry.Item1 == foreignKey.PrincipalToDependent)
                                {
                                    principalEntry = danglerEntry.Item2;
                                    break;
                                }
                            }
                        }

                        if (principalEntry != null)
                        {
                            var principalProperty = foreignKey.PrincipalKey.Properties[propertyIndex];
                            var principalValue    = principalEntry[principalProperty];
                            if (!principalProperty.ClrType.IsDefaultValue(principalValue))
                            {
                                if (principalEntry.HasTemporaryValue(principalProperty))
                                {
                                    entry.SetTemporaryValue(property, principalValue);
                                }
                                else
                                {
                                    entry[property] = principalValue;
                                }

                                return(principalEntry);
                            }
                        }

                        break;
                    }
                }
            }

            return(null);
        }
示例#5
0
 private static void SetGeneratedValue(InternalEntityEntry entry, IProperty property, object generatedValue, bool isTemporary)
 {
     if (generatedValue != null)
     {
         if (isTemporary)
         {
             entry.SetTemporaryValue(property, generatedValue);
         }
         else
         {
             entry[property] = generatedValue;
         }
     }
 }
示例#6
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual async Task <InternalEntityEntry?> PropagateValueAsync(
            InternalEntityEntry entry,
            IProperty property,
            CancellationToken cancellationToken = default)
        {
            Check.DebugAssert(property.IsForeignKey(), $"property {property} is not part of an FK");

            var generationProperty = property.FindGenerationProperty();
            var principalEntry     = TryPropagateValue(entry, property, generationProperty);

            if (principalEntry == null &&
                property.IsKey())
            {
                var valueGenerator = TryGetValueGenerator(
                    generationProperty,
                    generationProperty == property
                        ? entry.EntityType
                        : generationProperty?.DeclaringEntityType);

                if (valueGenerator != null)
                {
                    var value = await valueGenerator.NextAsync(new EntityEntry(entry), cancellationToken)
                                .ConfigureAwait(false);

                    if (valueGenerator.GeneratesTemporaryValues)
                    {
                        entry.SetTemporaryValue(property, value);
                    }
                    else
                    {
                        entry[property] = value;
                    }

                    if (!valueGenerator.GeneratesStableValues)
                    {
                        entry.MarkUnknown(property);
                    }
                }
            }

            return(principalEntry);
        }
示例#7
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual InternalEntityEntry?PropagateValue(InternalEntityEntry entry, IProperty property)
        {
            Check.DebugAssert(property.IsForeignKey(), $"property {property} is not part of an FK");

            var generationProperty = property.FindGenerationProperty();
            var principalEntry     = TryPropagateValue(entry, property, generationProperty);

            if (principalEntry == null &&
                property.IsKey() &&
                !property.IsForeignKeyToSelf())
            {
                var valueGenerator = TryGetValueGenerator(
                    generationProperty,
                    generationProperty == property
                        ? entry.EntityType
                        : generationProperty?.DeclaringEntityType);

                if (valueGenerator != null)
                {
                    var value = valueGenerator.Next(new EntityEntry(entry));

                    if (valueGenerator.GeneratesTemporaryValues)
                    {
                        entry.SetTemporaryValue(property, value);
                    }
                    else
                    {
                        entry[property] = value;
                    }

                    if (!valueGenerator.GeneratesStableValues)
                    {
                        entry.MarkUnknown(property);
                    }
                }
            }

            return(principalEntry);
        }