public virtual void Apply(InternalEntityTypeBuilder entityTypeBuilder, ForeignKey foreignKey)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            Check.NotNull(foreignKey, nameof(foreignKey));

            ConfigureKeyProperties(entityTypeBuilder, foreignKey.Properties);
        }
        public virtual void Apply(InternalEntityTypeBuilder entityTypeBuilder, ForeignKey foreignKey)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            Check.NotNull(foreignKey, nameof(foreignKey));

            SetValueGeneration(entityTypeBuilder, foreignKey.Properties);
            SetIdentity(entityTypeBuilder, foreignKey.Properties);
        }
        public virtual void Apply(InternalEntityTypeBuilder entityTypeBuilder, ForeignKey foreignKey)
        {
            var properties = foreignKey.Properties;
            SetValueGeneration(entityTypeBuilder, properties);

            var valueGeneratedOnAddProperty = FindValueGeneratedOnAddProperty(properties);
            if (valueGeneratedOnAddProperty != null
                && entityTypeBuilder.Metadata.FindPrimaryKey(properties) != null)
            {
                SetIdentity(entityTypeBuilder, valueGeneratedOnAddProperty);
            }
        }
        private bool ShouldFlip(
            ForeignKey foreignKey,
            IReadOnlyList<Property> currentDependentCandidateProperties,
            IReadOnlyList<Property> currentPrincipalCandidateProperties)
        {
            if (currentDependentCandidateProperties != null
                && currentPrincipalCandidateProperties == null)
            {
                return false;
            }

            if (currentDependentCandidateProperties == null
                && currentPrincipalCandidateProperties != null)
            {
                return true;
            }

            var navigationToPrincipal = foreignKey.DependentToPrincipal;
            var navigationToDependent = foreignKey.PrincipalToDependent;

            if (navigationToPrincipal == null
                && navigationToDependent != null)
            {
                return false;
            }

            if (navigationToPrincipal != null
                && navigationToDependent == null)
            {
                return true;
            }

            var model = foreignKey.DeclaringEntityType.Model;
            var principalPk = foreignKey.PrincipalEntityType.FindPrimaryKey();
            var principalPkReferenceThreshold = foreignKey.PrincipalKey == principalPk ? 1 : 0;
            var isPrincipalKeyReferenced = principalPk != null && model.FindReferencingForeignKeys(principalPk).Count() > principalPkReferenceThreshold;
            var dependentPk = foreignKey.DeclaringEntityType.FindPrimaryKey();
            var isDependentPrimaryKeyReferenced = dependentPk != null && model.FindReferencingForeignKeys(dependentPk).Any();

            if (isPrincipalKeyReferenced
                && !isDependentPrimaryKeyReferenced)
            {
                return false;
            }

            if (!isPrincipalKeyReferenced
                && isDependentPrimaryKeyReferenced)
            {
                return true;
            }

            return StringComparer.Ordinal.Compare(foreignKey.PrincipalEntityType.Name, foreignKey.DeclaringEntityType.Name) > 0;
        }
        public void Can_create_foreign_key()
        {
            var entityType = new Model().AddEntityType("E");
            var dependentProp = entityType.AddProperty("P", typeof(int));
            var principalProp = entityType.AddProperty("Id", typeof(int));
            entityType.GetOrSetPrimaryKey(principalProp);

            var foreignKey
                = new ForeignKey(new[] { dependentProp }, entityType.FindPrimaryKey(), entityType, entityType)
                {
                    IsUnique = true
                };

            Assert.Same(entityType, foreignKey.PrincipalEntityType);
            Assert.Same(principalProp, foreignKey.PrincipalKey.Properties.Single());
            Assert.Same(dependentProp, foreignKey.Properties.Single());
            Assert.True(foreignKey.IsUnique.Value);
            Assert.Same(entityType.FindPrimaryKey(), foreignKey.PrincipalKey);
        }
Exemple #6
0
        private bool RemoveForeignKey(ForeignKey foreignKey, ConfigurationSource configurationSource)
        {
            var entityBuilder = Entity(foreignKey.EntityType.Type, ConfigurationSource.Convention);

            return(entityBuilder.RemoveForeignKey(foreignKey, configurationSource));
        }
        private IReadOnlyList<Property> TryFindMatchingClrProperties(ForeignKey foreignKey, string baseName, bool onDependent)
        {
            var entityType = onDependent
                ? foreignKey.EntityType
                : foreignKey.PrincipalEntityType;
            var propertiesToReference = onDependent
                ? foreignKey.PrincipalKey.Properties
                : foreignKey.EntityType.FindPrimaryKey()?.Properties;

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

            var foreignKeyProperties = new List<Property>();
            foreach (var referencedProperty in propertiesToReference)
            {
                var property = TryGetProperty(entityType, baseName
                                                          + referencedProperty.Name, referencedProperty.ClrType.UnwrapNullableType());

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

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

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

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

            if (foreignKey.IsRequired == false
                && foreignKeyProperties.All(p => !((IProperty)p).IsNullable))
            {
                return null;
            }

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

            return foreignKeyProperties;
        }
        private IReadOnlyList<Property> GetCandidateForeignKeyProperties(ForeignKey foreignKey, bool onDependent)
        {
            var baseNames = new List<string>();
            var navigation = onDependent
                ? foreignKey.DependentToPrincipal
                : foreignKey.PrincipalToDependent;
            if (navigation != null)
            {
                baseNames.Add(navigation.Name);
            }

            var entityTypeToReference = onDependent
                ? foreignKey.PrincipalEntityType
                : foreignKey.EntityType;
            baseNames.Add(entityTypeToReference.DisplayName());

            baseNames.Add("");

            foreach (var baseName in baseNames)
            {
                var match = TryFindMatchingClrProperties(foreignKey, baseName, onDependent);
                if (match != null)
                {
                    return match;
                }
            }

            return null;
        }
        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",
                    ((IProperty)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;
                }
            }

            return foreignKeyProperties;
        }
        public void Can_create_foreign_key_with_non_pk_principal()
        {
            var entityType = new Model().AddEntityType("E");
            var keyProp = entityType.AddProperty("Id", typeof(int));
            var dependentProp = entityType.AddProperty("P", typeof(int));
            var principalProp = entityType.AddProperty("U", typeof(int));
            entityType.GetOrSetPrimaryKey(keyProp);
            var principalKey = entityType.AddKey(principalProp);

            var foreignKey
                = new ForeignKey(new[] { dependentProp }, principalKey, entityType, entityType)
                {
                    IsUnique = false
                };

            Assert.Same(entityType, foreignKey.PrincipalEntityType);
            Assert.Same(principalProp, foreignKey.PrincipalKey.Properties.Single());
            Assert.Same(dependentProp, foreignKey.Properties.Single());
            Assert.False(foreignKey.IsUnique.Value);
            Assert.Same(principalKey, foreignKey.PrincipalKey);
        }
        public void Can_change_cascade_delete_flag()
        {
            var entityType = new Model().AddEntityType("E");
            var keyProp = entityType.AddProperty("Id", typeof(int));
            var dependentProp = entityType.AddProperty("P", typeof(int));
            var principalProp = entityType.AddProperty("U", typeof(int));
            entityType.GetOrSetPrimaryKey(keyProp);
            var principalKey = entityType.AddKey(principalProp);

            var foreignKey
                = new ForeignKey(new[] { dependentProp }, principalKey, entityType, entityType);

            Assert.Null(foreignKey.DeleteBehavior);
            Assert.Equal(DeleteBehavior.Restrict, ((IForeignKey)foreignKey).DeleteBehavior);

            foreignKey.DeleteBehavior = DeleteBehavior.Cascade;

            Assert.Equal(DeleteBehavior.Cascade, foreignKey.DeleteBehavior);
            Assert.Equal(DeleteBehavior.Cascade, ((IForeignKey)foreignKey).DeleteBehavior);

            foreignKey.DeleteBehavior = DeleteBehavior.Restrict;

            Assert.Equal(DeleteBehavior.Restrict, foreignKey.DeleteBehavior);
            Assert.Equal(DeleteBehavior.Restrict, ((IForeignKey)foreignKey).DeleteBehavior);

            foreignKey.DeleteBehavior = null;

            Assert.Null(foreignKey.DeleteBehavior);
            Assert.Equal(DeleteBehavior.Restrict, ((IForeignKey)foreignKey).DeleteBehavior);
        }
        public void Setting_IsRequired_to_false_will_set_all_FK_properties_as_nullable()
        {
            var entityType = new Model().AddEntityType("E");
            var property = entityType.AddProperty("Id1", typeof(int));
            var property1 = entityType.AddProperty("Id2", typeof(string));
            entityType.GetOrSetPrimaryKey(new[]
            {
                property,
                property1
            });

            var dependentProp1 = entityType.AddProperty("P1", typeof(int?));
            var dependentProp2 = entityType.AddProperty("P2", typeof(string));

            var foreignKey = new ForeignKey(new[] { dependentProp1, dependentProp2 }, entityType.FindPrimaryKey(), entityType, entityType) { IsRequired = false };

            Assert.False(foreignKey.IsRequired.Value);
            Assert.True(dependentProp1.IsNullable.Value);
            Assert.True(dependentProp2.IsNullable.Value);
        }
        public void IsRequired_false_when_any_part_of_composite_FK_is_nullable()
        {
            var entityType = new Model().AddEntityType("E");
            var property = entityType.AddProperty("Id1", typeof(int));
            var property1 = entityType.AddProperty("Id2", typeof(string));
            entityType.GetOrSetPrimaryKey(new[]
            {
                property,
                property1
            });

            var dependentProp1 = entityType.AddProperty("P1", typeof(int));
            var dependentProp2 = entityType.AddProperty("P2", typeof(string));
            dependentProp2.IsNullable = true;

            var foreignKey = new ForeignKey(new[] { dependentProp1, dependentProp2 }, entityType.FindPrimaryKey(), entityType, entityType);

            Assert.False(foreignKey.IsRequired);
            Assert.False(((IForeignKey)foreignKey).IsRequired);

            dependentProp2.IsNullable = false;

            Assert.True(foreignKey.IsRequired);
            Assert.True(((IForeignKey)foreignKey).IsRequired);
        }
        public void IsRequired_false_for_composite_FK_by_default()
        {
            var entityType = new Model().AddEntityType("E");
            var property = entityType.AddProperty("Id1", typeof(int));
            var property1 = entityType.AddProperty("Id2", typeof(string));
            entityType.GetOrSetPrimaryKey(new[]
            {
                property,
                property1
            });

            var dependentProp1 = entityType.AddProperty("P1", typeof(int));
            var dependentProp2 = entityType.AddProperty("P2", typeof(string));

            var foreignKey = new ForeignKey(new[] { dependentProp1, dependentProp2 }, entityType.FindPrimaryKey(), entityType, entityType);

            Assert.Null(foreignKey.IsRequired);
            Assert.False(((IForeignKey)foreignKey).IsRequired);
        }
        public void IsRequired_and_IsUnique_null_when_dependent_property_nullable_by_default()
        {
            var entityType = new Model().AddEntityType("E");
            var property = entityType.AddProperty("Id", typeof(int));
            entityType.GetOrSetPrimaryKey(property);
            var dependentProp = entityType.AddProperty("P", typeof(int?));

            var foreignKey = new ForeignKey(new[] { dependentProp }, entityType.FindPrimaryKey(), entityType, entityType);

            Assert.Null(foreignKey.IsRequired);
            Assert.False(((IForeignKey)foreignKey).IsRequired);
            Assert.Null(foreignKey.IsUnique);
            Assert.False(((IForeignKey)foreignKey).IsUnique);
        }
        public void IsRequired_true_when_dependent_property_not_nullable()
        {
            var entityType = new Model().AddEntityType("E");
            var property = entityType.AddProperty("Id", typeof(int));
            entityType.GetOrSetPrimaryKey(property);
            var dependentProp = entityType.AddProperty("P", typeof(int));
            dependentProp.IsNullable = false;

            var foreignKey = new ForeignKey(new[] { dependentProp }, entityType.FindPrimaryKey(), entityType, entityType);

            Assert.True(foreignKey.IsRequired);
            Assert.True(((IForeignKey)foreignKey).IsRequired);
        }