Пример #1
0
        public void Can_finding_targets_for_same_hierarchy_foreign_keys()
        {
            var fk = CreateOneToManySameHierarchyFK();

            Assert.Same(fk.PrincipalEntityType, fk.ResolveOtherEntityType(fk.DeclaringEntityType));
            Assert.Same(fk.DeclaringEntityType, fk.ResolveOtherEntityType(fk.PrincipalEntityType));
            Assert.Same(fk.PrincipalToDependent, fk.FindNavigationsFrom(fk.PrincipalEntityType).SingleOrDefault());
            Assert.Same(fk.DependentToPrincipal, fk.FindNavigationsFrom(fk.DeclaringEntityType).SingleOrDefault());
            Assert.Same(fk.DependentToPrincipal, fk.FindNavigationsTo(fk.PrincipalEntityType).SingleOrDefault());
            Assert.Same(fk.PrincipalToDependent, fk.FindNavigationsTo(fk.DeclaringEntityType).SingleOrDefault());

            Assert.Equal(
                CoreStrings.IntraHierarchicalAmbiguousTargetEntityType(fk.DeclaringEntityType.DisplayName(), Property.Format(fk.Properties), fk.PrincipalEntityType.DisplayName(), fk.DeclaringEntityType.DisplayName()),
                Assert.Throws <InvalidOperationException>(() => fk.ResolveEntityTypeInHierarchy(fk.DeclaringEntityType)).Message);
            Assert.Equal(
                CoreStrings.IntraHierarchicalAmbiguousTargetEntityType(fk.PrincipalEntityType.DisplayName(), Property.Format(fk.Properties), fk.PrincipalEntityType.DisplayName(), fk.DeclaringEntityType.DisplayName()),
                Assert.Throws <InvalidOperationException>(() => fk.ResolveEntityTypeInHierarchy(fk.PrincipalEntityType)).Message);

            Assert.Equal(
                CoreStrings.IntraHierarchicalAmbiguousTargetEntityType(fk.DeclaringEntityType.DisplayName(), Property.Format(fk.Properties), fk.PrincipalEntityType.DisplayName(), fk.DeclaringEntityType.DisplayName()),
                Assert.Throws <InvalidOperationException>(() => fk.ResolveOtherEntityTypeInHierarchy(fk.DeclaringEntityType)).Message);
            Assert.Equal(
                CoreStrings.IntraHierarchicalAmbiguousTargetEntityType(fk.PrincipalEntityType.DisplayName(), Property.Format(fk.Properties), fk.PrincipalEntityType.DisplayName(), fk.DeclaringEntityType.DisplayName()),
                Assert.Throws <InvalidOperationException>(() => fk.ResolveOtherEntityTypeInHierarchy(fk.PrincipalEntityType)).Message);

            Assert.Equal(
                new[] { fk.PrincipalToDependent, fk.DependentToPrincipal }.Where(n => n != null),
                fk.FindNavigationsFromInHierarchy(fk.PrincipalEntityType));
            Assert.Equal(
                new[] { fk.PrincipalToDependent, fk.DependentToPrincipal }.Where(n => n != null),
                fk.FindNavigationsFromInHierarchy(fk.DeclaringEntityType));
            Assert.Equal(
                new[] { fk.PrincipalToDependent, fk.DependentToPrincipal }.Where(n => n != null),
                fk.FindNavigationsToInHierarchy(fk.PrincipalEntityType));
            Assert.Equal(
                new[] { fk.PrincipalToDependent, fk.DependentToPrincipal }.Where(n => n != null),
                fk.FindNavigationsToInHierarchy(fk.DeclaringEntityType));
        }
        /// <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>
        public static bool AreCompatible([NotNull] this IForeignKey foreignKey, [NotNull] IForeignKey duplicateForeignKey, bool shouldThrow)
        {
            var principalAnnotations          = foreignKey.PrincipalEntityType.Relational();
            var duplicatePrincipalAnnotations = duplicateForeignKey.PrincipalEntityType.Relational();

            if (!string.Equals(principalAnnotations.Schema, duplicatePrincipalAnnotations.Schema, StringComparison.OrdinalIgnoreCase) ||
                !string.Equals(principalAnnotations.TableName, duplicatePrincipalAnnotations.TableName, StringComparison.OrdinalIgnoreCase))
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyPrincipalTableMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  Format(foreignKey.DeclaringEntityType.Relational()),
                                  foreignKey.Relational().Name,
                                  Format(principalAnnotations),
                                  Format(duplicatePrincipalAnnotations)));
                }

                return(false);
            }

            if (!foreignKey.Properties.Select(p => p.Relational().ColumnName)
                .SequenceEqual(duplicateForeignKey.Properties.Select(p => p.Relational().ColumnName)))
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyColumnMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  Format(foreignKey.DeclaringEntityType.Relational()),
                                  foreignKey.Relational().Name,
                                  foreignKey.Properties.FormatColumns(),
                                  duplicateForeignKey.Properties.FormatColumns()));
                }

                return(false);
            }

            if (!foreignKey.PrincipalKey.Properties
                .Select(p => p.Relational().ColumnName)
                .SequenceEqual(
                    duplicateForeignKey.PrincipalKey.Properties
                    .Select(p => p.Relational().ColumnName)))
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyPrincipalColumnMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  Format(foreignKey.DeclaringEntityType.Relational()),
                                  foreignKey.Relational().Name,
                                  foreignKey.PrincipalKey.Properties.FormatColumns(),
                                  duplicateForeignKey.PrincipalKey.Properties.FormatColumns()));
                }

                return(false);
            }

            if (foreignKey.IsUnique != duplicateForeignKey.IsUnique)
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyUniquenessMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  Format(foreignKey.DeclaringEntityType.Relational()),
                                  foreignKey.Relational().Name));
                }

                return(false);
            }

            if (foreignKey.DeleteBehavior != duplicateForeignKey.DeleteBehavior)
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.DuplicateForeignKeyDeleteBehaviorMismatch(
                                  Property.Format(foreignKey.Properties),
                                  foreignKey.DeclaringEntityType.DisplayName(),
                                  Property.Format(duplicateForeignKey.Properties),
                                  duplicateForeignKey.DeclaringEntityType.DisplayName(),
                                  Format(foreignKey.DeclaringEntityType.Relational()),
                                  foreignKey.Relational().Name,
                                  foreignKey.DeleteBehavior,
                                  duplicateForeignKey.DeleteBehavior));
                }

                return(false);
            }

            return(true);
        }
Пример #3
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>
        public static bool AreCompatible(
            [NotNull] EntityType principalEntityType,
            [NotNull] EntityType dependentEntityType,
            [CanBeNull] PropertyInfo navigationToPrincipal,
            [CanBeNull] PropertyInfo navigationToDependent,
            [CanBeNull] IReadOnlyList <Property> dependentProperties,
            [CanBeNull] IReadOnlyList <Property> principalProperties,
            bool?unique,
            bool?required,
            bool shouldThrow)
        {
            Check.NotNull(principalEntityType, nameof(principalEntityType));
            Check.NotNull(dependentEntityType, nameof(dependentEntityType));

            if (principalEntityType.HasDelegatedIdentity() &&
                principalEntityType.ClrType == dependentEntityType.ClrType)
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(
                              CoreStrings.ForeignKeySelfReferencingDelegatedIdentity(dependentEntityType.DisplayName()));
                }
                return(false);
            }

            if (navigationToPrincipal != null &&
                !Internal.Navigation.IsCompatible(
                    navigationToPrincipal,
                    dependentEntityType.ClrType,
                    principalEntityType.ClrType,
                    shouldBeCollection: false,
                    shouldThrow: shouldThrow))
            {
                return(false);
            }

            if (navigationToDependent != null &&
                !Internal.Navigation.IsCompatible(
                    navigationToDependent,
                    principalEntityType.ClrType,
                    dependentEntityType.ClrType,
                    shouldBeCollection: !unique,
                    shouldThrow: shouldThrow))
            {
                return(false);
            }

            // FKs are not allowed to use properties from inherited keys since this could result in an ambiguous value space
            if (dependentProperties != null &&
                dependentEntityType.BaseType != null)
            {
                var inheritedKey = dependentProperties.SelectMany(p => p.GetContainingKeys().Where(k => k.DeclaringEntityType != dependentEntityType)).FirstOrDefault();
                if (inheritedKey != null)
                {
                    if (shouldThrow)
                    {
                        throw new InvalidOperationException(
                                  CoreStrings.ForeignKeyPropertyInKey(
                                      dependentProperties.First(p => inheritedKey.Properties.Contains(p)).Name,
                                      dependentEntityType.DisplayName(),
                                      Property.Format(inheritedKey.Properties),
                                      inheritedKey.DeclaringEntityType.DisplayName()));
                    }
                    return(false);
                }
            }

            if (dependentProperties != null &&
                !CanPropertiesBeRequired(dependentProperties, required, dependentEntityType, true))
            {
                return(false);
            }

            if (principalProperties != null &&
                dependentProperties != null &&
                !AreCompatible(
                    principalProperties,
                    dependentProperties,
                    principalEntityType,
                    dependentEntityType,
                    shouldThrow))
            {
                return(false);
            }

            return(true);
        }