/// <summary>
        ///     <para>
        ///         Initializes a new instance of the <see cref="ReferenceCollectionBuilder" /> class.
        ///     </para>
        /// </summary>
        /// <param name="builder"> The internal builder being used to configure this relationship. </param>
        /// <param name="oldBuilder"> A builder to copy configuration from. </param>
        /// <param name="foreignKeySet">
        ///     A value indicating whether the foreign key properties have been configured in this chain of configuration calls.
        /// </param>
        /// <param name="principalKeySet">
        ///     A value indicating whether the principal key properties have been configured in this chain of configuration calls.
        /// </param>
        /// <param name="requiredSet">
        ///     A value indicating whether required/optional has been configured in this chain of configuration calls.
        /// </param>
        protected ReferenceCollectionBuilder(InternalRelationshipBuilder builder,
                                             ReferenceCollectionBuilder oldBuilder,
                                             bool foreignKeySet   = false,
                                             bool principalKeySet = false,
                                             bool requiredSet     = false)
        {
            Check.NotNull(builder, nameof(builder));

            Builder = builder;
            if (oldBuilder != null)
            {
                _foreignKeyProperties = foreignKeySet
                    ? builder.Metadata.Properties
                    : oldBuilder._foreignKeyProperties;
                _principalKeyProperties = principalKeySet
                    ? builder.Metadata.PrincipalKey.Properties
                    : oldBuilder._principalKeyProperties;
                _required = requiredSet
                    ? builder.Metadata.IsRequired
                    : oldBuilder._required;

                var foreignKey = builder.Metadata;
                ForeignKey.AreCompatible(
                    foreignKey.PrincipalEntityType,
                    foreignKey.DeclaringEntityType,
                    foreignKey.DependentToPrincipal?.Name,
                    foreignKey.PrincipalToDependent?.Name,
                    _foreignKeyProperties,
                    _principalKeyProperties,
                    foreignKey.IsUnique,
                    _required,
                    shouldThrow: true);
            }
        }
Exemplo n.º 2
0
        protected RelationshipBuilderBase(
            [NotNull] InternalForeignKeyBuilder builder,
            [NotNull] RelationshipBuilderBase oldBuilder,
            bool foreignKeySet   = false,
            bool principalKeySet = false,
            bool requiredSet     = false)
        {
            Check.NotNull(builder, nameof(builder));

            Builder               = builder;
            PrincipalEntityType   = oldBuilder.PrincipalEntityType;
            DependentEntityType   = oldBuilder.DependentEntityType;
            _foreignKeyProperties = foreignKeySet
                ? builder.Metadata.Properties
                : ((EntityType)oldBuilder.DependentEntityType).Builder.GetActualProperties(oldBuilder._foreignKeyProperties, null);
            _principalKeyProperties = principalKeySet
                ? builder.Metadata.PrincipalKey.Properties
                : ((EntityType)oldBuilder.PrincipalEntityType).Builder.GetActualProperties(oldBuilder._principalKeyProperties, null);
            _required = requiredSet
                ? builder.Metadata.IsRequired
                : oldBuilder._required;

            var foreignKey = builder.Metadata;

            ForeignKey.AreCompatible(
                (EntityType)oldBuilder.PrincipalEntityType,
                (EntityType)oldBuilder.DependentEntityType,
                foreignKey.DependentToPrincipal?.GetIdentifyingMemberInfo(),
                foreignKey.PrincipalToDependent?.GetIdentifyingMemberInfo(),
                _foreignKeyProperties,
                _principalKeyProperties,
                foreignKey.IsUnique,
                shouldThrow: true);
        }
        private static IReadOnlyList <Property> GetCompatiblePrimaryKeyProperties(EntityType dependentEntityType, EntityType principalEntityType, IReadOnlyList <Property> propertiesToReference)
        {
            var dependentPkProperties = dependentEntityType.FindPrimaryKey()?.Properties;

            return((dependentPkProperties != null) &&
                   ForeignKey.AreCompatible(
                       propertiesToReference,
                       dependentPkProperties,
                       principalEntityType,
                       dependentEntityType,
                       false)
                ? dependentPkProperties
                : null);
        }
Exemplo n.º 4
0
        /// <summary>
        ///     <para>
        ///         Initializes a new instance of the <see cref="ReferenceReferenceBuilder" /> class.
        ///     </para>
        /// </summary>
        /// <param name="builder"> The internal builder being used to configure this relationship. </param>
        /// <param name="oldBuilder"> A builder to copy configuration from. </param>
        /// <param name="inverted">
        ///     A value indicating whether to reverse the direction of the relationship.
        /// </param>
        /// <param name="foreignKeySet">
        ///     A value indicating whether the foreign key properties have been configured in this chain of configuration calls.
        /// </param>
        /// <param name="principalKeySet">
        ///     A value indicating whether the principal key properties have been configured in this chain of configuration calls.
        /// </param>
        /// <param name="requiredSet">
        ///     A value indicating whether required/optional has been configured in this chain of configuration calls.
        /// </param>
        protected ReferenceReferenceBuilder(
            InternalRelationshipBuilder builder,
            ReferenceReferenceBuilder oldBuilder,
            bool inverted        = false,
            bool foreignKeySet   = false,
            bool principalKeySet = false,
            bool requiredSet     = false)
        {
            Builder = builder;
            if (oldBuilder != null)
            {
                if (inverted)
                {
                    if ((oldBuilder._foreignKeyProperties != null) ||
                        (oldBuilder._principalKeyProperties != null))

                    {
                        throw new InvalidOperationException(CoreStrings.RelationshipCannotBeInverted);
                    }

                    var navigationName = _navigationToDependentName;
                    _navigationToDependentName = _navigationToPrincipalName;
                    _navigationToPrincipalName = navigationName;
                }

                _foreignKeyProperties = foreignKeySet
                    ? builder.Metadata.Properties
                    : oldBuilder._foreignKeyProperties;
                _principalKeyProperties = principalKeySet
                    ? builder.Metadata.PrincipalKey.Properties
                    : oldBuilder._principalKeyProperties;
                _required = requiredSet
                    ? builder.Metadata.IsRequired
                    : oldBuilder._required;

                var foreignKey = builder.Metadata;
                ForeignKey.AreCompatible(
                    foreignKey.PrincipalEntityType,
                    foreignKey.DeclaringEntityType,
                    _navigationToPrincipalName,
                    _navigationToDependentName,
                    _foreignKeyProperties,
                    _principalKeyProperties,
                    foreignKey.IsUnique,
                    _required,
                    shouldThrow: true);
            }
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected ReferenceReferenceBuilderBase(
            InternalRelationshipBuilder builder,
            ReferenceReferenceBuilderBase oldBuilder,
            bool inverted        = false,
            bool foreignKeySet   = false,
            bool principalKeySet = false,
            bool requiredSet     = false)
        {
            Builder = builder;

            if (oldBuilder != null)
            {
                if (inverted)
                {
                    if (oldBuilder._foreignKeyProperties != null ||
                        oldBuilder._principalKeyProperties != null)
                    {
                        throw new InvalidOperationException(CoreStrings.RelationshipCannotBeInverted);
                    }
                }

                DeclaringEntityType = oldBuilder.DeclaringEntityType;
                RelatedEntityType   = oldBuilder.RelatedEntityType;

                _foreignKeyProperties = foreignKeySet
                    ? builder.Metadata.Properties
                    : oldBuilder._foreignKeyProperties;
                _principalKeyProperties = principalKeySet
                    ? builder.Metadata.PrincipalKey.Properties
                    : oldBuilder._principalKeyProperties;
                _required = requiredSet
                    ? builder.Metadata.IsRequired
                    : oldBuilder._required;

                var foreignKey = builder.Metadata;
                ForeignKey.AreCompatible(
                    foreignKey.PrincipalEntityType,
                    foreignKey.DeclaringEntityType,
                    foreignKey.DependentToPrincipal?.PropertyInfo,
                    foreignKey.PrincipalToDependent?.PropertyInfo,
                    _foreignKeyProperties,
                    _principalKeyProperties,
                    foreignKey.IsUnique,
                    _required,
                    shouldThrow: true);
            }
        }
Exemplo n.º 6
0
        private static IReadOnlyList <IConventionProperty>?GetCompatiblePrimaryKeyProperties(
            IConventionEntityType dependentEntityType,
            IConventionEntityType principalEntityType,
            IReadOnlyList <IConventionProperty> propertiesToReference)
        {
            var dependentPkProperties = dependentEntityType.FindPrimaryKey()?.Properties;

            return(dependentPkProperties != null &&
                   ForeignKey.AreCompatible(
                       propertiesToReference,
                       dependentPkProperties,
                       principalEntityType,
                       dependentEntityType,
                       shouldThrow: false)
                    ? dependentPkProperties
                    : null);
        }
Exemplo n.º 7
0
        private IReadOnlyList <Property> GetCompatiblePrimaryKeyProperties(EntityType dependentEntityType, EntityType principalEntityType, IReadOnlyList <Property> propertiesToReference)
        {
            var dependentPkProperties = dependentEntityType.FindPrimaryKey()?.Properties;

            if (dependentPkProperties != null &&
                ForeignKey.AreCompatible(
                    propertiesToReference,
                    dependentPkProperties,
                    principalEntityType,
                    dependentEntityType,
                    shouldThrow: false))
            {
                return(dependentPkProperties);
            }

            return(null);
        }
Exemplo n.º 8
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected ReferenceCollectionBuilderBase(
            InternalRelationshipBuilder builder,
            ReferenceCollectionBuilderBase oldBuilder,
            bool foreignKeySet   = false,
            bool principalKeySet = false,
            bool requiredSet     = false)
        {
            Check.NotNull(builder, nameof(builder));

            Builder = builder;
            if (oldBuilder != null)
            {
                PrincipalEntityType   = oldBuilder.PrincipalEntityType;
                DependentEntityType   = oldBuilder.DependentEntityType;
                _foreignKeyProperties = foreignKeySet
                    ? builder.Metadata.Properties
                    : DependentEntityType.Builder.GetActualProperties(oldBuilder._foreignKeyProperties, null);
                _principalKeyProperties = principalKeySet
                    ? builder.Metadata.PrincipalKey.Properties
                    : PrincipalEntityType.Builder.GetActualProperties(oldBuilder._principalKeyProperties, null);
                _required = requiredSet
                    ? builder.Metadata.IsRequired
                    : oldBuilder._required;

                var foreignKey = builder.Metadata;
                ForeignKey.AreCompatible(
                    PrincipalEntityType,
                    DependentEntityType,
                    foreignKey.DependentToPrincipal?.GetIdentifyingMemberInfo(),
                    foreignKey.PrincipalToDependent?.GetIdentifyingMemberInfo(),
                    _foreignKeyProperties,
                    _principalKeyProperties,
                    foreignKey.IsUnique,
                    _required,
                    true);
            }
        }
Exemplo n.º 9
0
        private bool TryFindMatchingProperties(
            IConventionForeignKey foreignKey,
            string baseName,
            bool onDependent,
            bool matchPk,
            out IReadOnlyList <IConventionProperty>?match)
        {
            match = null;
            var dependentEntityType = onDependent
                ? foreignKey.DeclaringEntityType
                : foreignKey.PrincipalEntityType;
            var principalEntityType = onDependent
                ? foreignKey.PrincipalEntityType
                : foreignKey.DeclaringEntityType;
            var propertiesToReference = onDependent
                ? foreignKey.PrincipalKey.Properties
                : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties;

            if (propertiesToReference == null)
            {
                return(false);
            }

            var foreignKeyProperties = new IConventionProperty[propertiesToReference.Count];
            var matchFound           = true;

            for (var i = 0; i < propertiesToReference.Count; i++)
            {
                var referencedProperty = propertiesToReference[i];
                var property           = TryGetProperty(
                    dependentEntityType,
                    baseName, referencedProperty.Name);

                if (property == null)
                {
                    matchFound = false;
                    continue;
                }

                foreignKeyProperties[i] = property;
            }

            if (!matchFound &&
                propertiesToReference.Count == 1 &&
                baseName.Length > 0)
            {
                var property = TryGetProperty(
                    dependentEntityType,
                    baseName, "Id");

                if (property != null)
                {
                    foreignKeyProperties[0] = property;
                    matchFound = true;
                }
            }

            if (!matchFound)
            {
                return(false);
            }

            if (!ForeignKey.AreCompatible(
                    propertiesToReference,
                    foreignKeyProperties,
                    principalEntityType,
                    dependentEntityType,
                    shouldThrow: false))
            {
                if (propertiesToReference.All(
                        p => !p.IsImplicitlyCreated() ||
                        p.GetConfigurationSource().Overrides(ConfigurationSource.DataAnnotation)))
                {
                    var dependentNavigationSpec = onDependent
                        ? foreignKey.DependentToPrincipal?.Name
                        : foreignKey.PrincipalToDependent?.Name;
                    dependentNavigationSpec = dependentEntityType.DisplayName()
                                              + (string.IsNullOrEmpty(dependentNavigationSpec)
                            ? string.Empty
                            : "." + dependentNavigationSpec);

                    var principalNavigationSpec = onDependent
                        ? foreignKey.PrincipalToDependent?.Name
                        : foreignKey.DependentToPrincipal?.Name;
                    principalNavigationSpec = principalEntityType.DisplayName()
                                              + (string.IsNullOrEmpty(principalNavigationSpec)
                            ? string.Empty
                            : "." + principalNavigationSpec);

                    Dependencies.Logger.IncompatibleMatchingForeignKeyProperties(
                        dependentNavigationSpec, principalNavigationSpec,
                        foreignKeyProperties, propertiesToReference);
                }

                // Stop searching if match found, but is incompatible
                return(true);
            }

            foreach (var key in dependentEntityType.GetKeys())
            {
                var isKeyContainedInForeignKey = true;
                // ReSharper disable once LoopCanBeConvertedToQuery
                // ReSharper disable once ForCanBeConvertedToForeach
                for (var i = 0; i < key.Properties.Count; i++)
                {
                    if (!foreignKeyProperties.Contains(key.Properties[i]))
                    {
                        isKeyContainedInForeignKey = false;
                        break;
                    }
                }

                if (isKeyContainedInForeignKey &&
                    (!foreignKey.IsUnique ||
                     (key.IsPrimaryKey() &&
                      !matchPk)))
                {
                    // Stop searching if match found, but is incompatible
                    return(true);
                }
            }

            match = foreignKeyProperties;
            return(true);
        }
        private bool TryFindMatchingProperties(
            ForeignKey foreignKey, string baseName, bool onDependent, bool matchPK, out IReadOnlyList <Property> match)
        {
            match = null;
            var dependentEntityType = onDependent
                ? foreignKey.DeclaringEntityType
                : foreignKey.PrincipalEntityType;
            var principalEntityType = onDependent
                ? foreignKey.PrincipalEntityType
                : foreignKey.DeclaringEntityType;
            var propertiesToReference = onDependent
                ? foreignKey.PrincipalKey.Properties
                : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties;

            if (propertiesToReference == null)
            {
                return(false);
            }

            var foreignKeyProperties = new Property[propertiesToReference.Count];
            var matchFound           = true;

            for (var i = 0; i < propertiesToReference.Count; i++)
            {
                var referencedProperty = propertiesToReference[i];
                var property           = TryGetProperty(
                    dependentEntityType,
                    baseName, referencedProperty.Name);

                if (property == null)
                {
                    matchFound = false;
                    continue;
                }

                foreignKeyProperties[i] = property;
            }

            if (!matchFound &&
                propertiesToReference.Count == 1 &&
                baseName.Length > 0)
            {
                var property = TryGetProperty(
                    dependentEntityType,
                    baseName, "Id");

                if (property != null)
                {
                    foreignKeyProperties[0] = property;
                    matchFound = true;
                }
            }

            if (!matchFound)
            {
                return(false);
            }

            if (!ForeignKey.AreCompatible(
                    propertiesToReference,
                    foreignKeyProperties,
                    principalEntityType,
                    dependentEntityType,
                    false))
            {
                if (propertiesToReference.All(
                        p => !p.IsShadowProperty ||
                        p.GetConfigurationSource().Overrides(ConfigurationSource.DataAnnotation)))
                {
                    Logger.IncompatibleMatchingForeignKeyProperties(foreignKeyProperties, propertiesToReference);
                }

                // Stop searching if match found, but is incompatible
                return(true);
            }

            foreach (var key in dependentEntityType.GetKeys())
            {
                var isKeyContainedInForeignKey = true;
                // ReSharper disable once LoopCanBeConvertedToQuery
                // ReSharper disable once ForCanBeConvertedToForeach
                for (var i = 0; i < key.Properties.Count; i++)
                {
                    if (!foreignKeyProperties.Contains(key.Properties[i]))
                    {
                        isKeyContainedInForeignKey = false;
                        break;
                    }

                    if (!foreignKey.IsUnique)
                    {
                        // Stop searching if match found, but is incompatible
                        return(true);
                    }
                }

                if (isKeyContainedInForeignKey &&
                    key.IsPrimaryKey() &&
                    !matchPK)
                {
                    // Stop searching if match found, but is incompatible
                    return(true);
                }
            }

            match = foreignKeyProperties;
            return(true);
        }
Exemplo n.º 11
0
        private IReadOnlyList <Property> FindMatchingNonShadowProperties(
            ForeignKey foreignKey, string baseName, bool onDependent)
        {
            var dependentEntityType = onDependent
                ? foreignKey.DeclaringEntityType
                : foreignKey.PrincipalEntityType;
            var principalEntityType = onDependent
                ? foreignKey.PrincipalEntityType
                : foreignKey.DeclaringEntityType;
            var propertiesToReference = onDependent
                ? foreignKey.PrincipalKey.Properties
                : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties;

            if (propertiesToReference == null)
            {
                return(null);
            }

            var foreignKeyProperties = new List <Property>();

            foreach (IProperty referencedProperty in propertiesToReference)
            {
                var property = TryGetProperty(dependentEntityType,
                                              baseName + referencedProperty.Name,
                                              referencedProperty.ClrType.UnwrapNullableType());

                if (property != null)
                {
                    foreignKeyProperties.Add(property);
                }
            }

            if ((propertiesToReference.Count == 1) &&
                (foreignKeyProperties.Count == 0))
            {
                var property = TryGetProperty(dependentEntityType,
                                              baseName + "Id",
                                              propertiesToReference.Single().ClrType.UnwrapNullableType());

                if (property != null)
                {
                    foreignKeyProperties.Add(property);
                }
            }

            if (foreignKeyProperties.Count < propertiesToReference.Count)
            {
                return(null);
            }

            if (!ForeignKey.AreCompatible(
                    propertiesToReference,
                    foreignKeyProperties,
                    principalEntityType,
                    dependentEntityType,
                    shouldThrow: false))
            {
                return(null);
            }

            var primaryKey = dependentEntityType.FindPrimaryKey();

            if (primaryKey != null)
            {
                if (foreignKeyProperties.All(property => primaryKey.Properties.Contains(property)))
                {
                    return(null);
                }
            }

            // Don't match with only Id since it is ambigious. PK in dependent entity used as FK is matched elsewhere
            if ((foreignKeyProperties.Count == 1) &&
                (foreignKeyProperties.Single().Name == "Id"))
            {
                return(null);
            }

            return(foreignKeyProperties);
        }
        private IReadOnlyList <Property> FindMatchingProperties(
            ForeignKey foreignKey, string baseName, bool onDependent, bool matchPK = false)
        {
            var dependentEntityType = onDependent
                ? foreignKey.DeclaringEntityType
                : foreignKey.PrincipalEntityType;
            var principalEntityType = onDependent
                ? foreignKey.PrincipalEntityType
                : foreignKey.DeclaringEntityType;
            var propertiesToReference = onDependent
                ? foreignKey.PrincipalKey.Properties
                : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties;

            if (propertiesToReference == null)
            {
                return(null);
            }

            var foreignKeyProperties = new Property[propertiesToReference.Count];
            var matchFound           = true;

            for (var i = 0; i < propertiesToReference.Count; i++)
            {
                var referencedProperty = propertiesToReference[i];
                var property           = TryGetProperty(dependentEntityType,
                                                        baseName, referencedProperty.Name,
                                                        referencedProperty.ClrType.UnwrapNullableType());

                if (property == null)
                {
                    matchFound = false;
                    continue;
                }

                foreignKeyProperties[i] = property;
            }

            if (!matchFound &&
                propertiesToReference.Count == 1)
            {
                var property = TryGetProperty(dependentEntityType,
                                              baseName, "Id",
                                              propertiesToReference.Single().ClrType.UnwrapNullableType());

                if (property != null)
                {
                    foreignKeyProperties[0] = property;
                    matchFound = true;
                }
            }

            if (!matchFound)
            {
                return(null);
            }

            if (!ForeignKey.AreCompatible(
                    propertiesToReference,
                    foreignKeyProperties,
                    principalEntityType,
                    dependentEntityType,
                    false))
            {
                return(null);
            }

            foreach (var key in dependentEntityType.GetKeys())
            {
                if (key.Properties.All(property => foreignKeyProperties.Contains(property)) &&
                    (!foreignKey.IsUnique ||
                     (key.IsPrimaryKey() && !matchPK)))
                {
                    return(null);
                }
            }

            // Don't match with only Id since it is ambiguous. PK in dependent entity used as FK is matched elsewhere
            if (foreignKeyProperties.Length == 1 &&
                foreignKeyProperties[0].Name == "Id")
            {
                return(null);
            }

            return(foreignKeyProperties);
        }
Exemplo n.º 13
0
        private IReadOnlyList <Property> FindMatchingProperties(
            ForeignKey foreignKey, string baseName, bool onDependent, bool matchPK = false)
        {
            var dependentEntityType = onDependent
                ? foreignKey.DeclaringEntityType
                : foreignKey.PrincipalEntityType;
            var principalEntityType = onDependent
                ? foreignKey.PrincipalEntityType
                : foreignKey.DeclaringEntityType;
            var propertiesToReference = onDependent
                ? foreignKey.PrincipalKey.Properties
                : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties;

            if (propertiesToReference == null)
            {
                return(null);
            }

            var foreignKeyProperties = new Property[propertiesToReference.Count];
            var matchFound           = true;

            for (var i = 0; i < propertiesToReference.Count; i++)
            {
                var referencedProperty = propertiesToReference[i];
                var property           = TryGetProperty(
                    dependentEntityType,
                    baseName, referencedProperty.Name);

                if (property == null)
                {
                    matchFound = false;
                    continue;
                }

                foreignKeyProperties[i] = property;
            }

            if (!matchFound &&
                propertiesToReference.Count == 1)
            {
                var property = TryGetProperty(
                    dependentEntityType,
                    baseName, "Id");

                if (property != null)
                {
                    foreignKeyProperties[0] = property;
                    matchFound = true;
                }
            }

            if (!matchFound)
            {
                return(null);
            }

            if (!ForeignKey.AreCompatible(
                    propertiesToReference,
                    foreignKeyProperties,
                    principalEntityType,
                    dependentEntityType,
                    false))
            {
                _logger.IncompatibleMatchingForeignKeyProperties(foreignKeyProperties, propertiesToReference);
                return(new Property[0]);
            }

            foreach (var key in dependentEntityType.GetKeys())
            {
                if (key.Properties.All(property => foreignKeyProperties.Contains(property)) &&
                    (!foreignKey.IsUnique ||
                     (key.IsPrimaryKey() && !matchPK)))
                {
                    return(new Property[0]);
                }
            }

            return(foreignKeyProperties);
        }