private static void TryBuildRelationship(
            [NotNull] InternalEntityTypeBuilder sourceBuilder,
            [NotNull] InternalEntityTypeBuilder targetBuilder,
            [NotNull] PropertyInfo navigationToTarget,
            [CanBeNull] PropertyInfo navigationToSource)
        {
            var isToTargetNavigationCollection = navigationToTarget.PropertyType.TryGetSequenceType() != null;

            if (isToTargetNavigationCollection)
            {
                if (navigationToSource?.PropertyType.TryGetSequenceType() != null)
                {
                    // TODO: Support many to many
                    return;
                }

                targetBuilder.Relationship(
                    sourceBuilder,
                    targetBuilder,
                    navigationToSource?.Name,
                    navigationToTarget.Name,
                    configurationSource: ConfigurationSource.Convention, isUnique: false, strictPrincipal: true);
            }
            else
            {
                if (navigationToSource == null)
                {
                    targetBuilder.Relationship(
                        targetBuilder,
                        sourceBuilder,
                        navigationToTarget.Name,
                        navigationToDependentName: null,
                        configurationSource: ConfigurationSource.Convention, isUnique: null, strictPrincipal: false);
                }
                else
                {
                    if (navigationToSource.PropertyType.TryGetSequenceType() == null)
                    {
                        targetBuilder.Relationship(
                            sourceBuilder,
                            targetBuilder,
                            navigationToSource.Name,
                            navigationToTarget.Name,
                            configurationSource: ConfigurationSource.Convention, isUnique: true, strictPrincipal: false);
                    }
                }
            }
        }
        private static void CreateRelationships(
            IReadOnlyList <RelationshipCandidate> relationshipCandidates, InternalEntityTypeBuilder entityTypeBuilder)
        {
            foreach (var relationshipCandidate in relationshipCandidates)
            {
                Debug.Assert(relationshipCandidate.NavigationProperties.Count > 0);
                if ((relationshipCandidate.NavigationProperties.Count > 1 &&
                     relationshipCandidate.InverseProperties.Count > 0) ||
                    relationshipCandidate.InverseProperties.Count > 1)
                {
                    foreach (var navigationProperty in relationshipCandidate.NavigationProperties)
                    {
                        var existingForeignKey = entityTypeBuilder.Metadata.FindDeclaredNavigation(navigationProperty.Name)?.ForeignKey;
                        existingForeignKey?.DeclaringEntityType.Builder
                        .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                    }

                    foreach (var inverseProperty in relationshipCandidate.InverseProperties)
                    {
                        var existingForeignKey = relationshipCandidate.TargetTypeBuilder.Metadata
                                                 .FindDeclaredNavigation(inverseProperty.Name)?.ForeignKey;
                        existingForeignKey?.DeclaringEntityType.Builder
                        .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                    }

                    continue;
                }

                foreach (var navigation in relationshipCandidate.NavigationProperties)
                {
                    var inverse = relationshipCandidate.InverseProperties.SingleOrDefault();
                    if (inverse == null)
                    {
                        entityTypeBuilder.Navigation(
                            relationshipCandidate.TargetTypeBuilder,
                            navigation,
                            ConfigurationSource.Convention);
                    }
                    else
                    {
                        entityTypeBuilder.Relationship(
                            relationshipCandidate.TargetTypeBuilder,
                            navigation,
                            inverse,
                            ConfigurationSource.Convention);
                    }
                }
            }
        }
        private void CreateRelationships(
            IReadOnlyList <RelationshipCandidate> relationshipCandidates, InternalEntityTypeBuilder entityTypeBuilder)
        {
            foreach (var relationshipCandidate in relationshipCandidates)
            {
                if ((relationshipCandidate.NavigationProperties.Count > 1 &&
                     relationshipCandidate.InverseProperties.Count > 0) ||
                    relationshipCandidate.InverseProperties.Count > 1)
                {
                    foreach (var navigationProperty in relationshipCandidate.NavigationProperties)
                    {
                        var existingForeignKey = entityTypeBuilder.Metadata.FindDeclaredNavigation(navigationProperty.Name)?.ForeignKey;
                        if (existingForeignKey != null)
                        {
                            entityTypeBuilder.ModelBuilder.Entity(existingForeignKey.DeclaringEntityType.Name, ConfigurationSource.Convention)
                            .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                        }
                    }

                    foreach (var inverseProperty in relationshipCandidate.InverseProperties)
                    {
                        var existingForeignKey = relationshipCandidate.TargetTypeBuilder.Metadata.FindDeclaredNavigation(inverseProperty.Name)?.ForeignKey;
                        if (existingForeignKey != null)
                        {
                            entityTypeBuilder.ModelBuilder.Entity(existingForeignKey.DeclaringEntityType.Name, ConfigurationSource.Convention)
                            .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                        }
                    }

                    break;
                }

                foreach (var navigation in relationshipCandidate.NavigationProperties)
                {
                    var inverse = relationshipCandidate.InverseProperties.SingleOrDefault();
                    entityTypeBuilder.Relationship(
                        relationshipCandidate.TargetTypeBuilder,
                        navigation,
                        inverse,
                        ConfigurationSource.Convention);
                }
            }
        }
예제 #4
0
        private InternalRelationshipBuilder ConfigureInverseNavigation(
            InternalEntityTypeBuilder entityTypeBuilder,
            PropertyInfo navigationPropertyInfo,
            InternalEntityTypeBuilder targetEntityTypeBuilder,
            InversePropertyAttribute attribute)
        {
            var entityType    = entityTypeBuilder.Metadata;
            var targetClrType = targetEntityTypeBuilder.Metadata.ClrType;
            var inverseNavigationPropertyInfo = targetClrType.GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, attribute.Property, StringComparison.OrdinalIgnoreCase));

            if (inverseNavigationPropertyInfo == null ||
                !FindCandidateNavigationPropertyType(inverseNavigationPropertyInfo).GetTypeInfo()
                .IsAssignableFrom(entityType.ClrType.GetTypeInfo()))
            {
                throw new InvalidOperationException(
                          CoreStrings.InvalidNavigationWithInverseProperty(
                              navigationPropertyInfo.Name, entityType.DisplayName(), attribute.Property, targetClrType.ShortDisplayName()));
            }

            if (Equals(inverseNavigationPropertyInfo, navigationPropertyInfo))
            {
                throw new InvalidOperationException(
                          CoreStrings.SelfReferencingNavigationWithInverseProperty(
                              navigationPropertyInfo.Name,
                              entityType.DisplayName(),
                              navigationPropertyInfo.Name,
                              entityType.DisplayName()));
            }

            // Check for InversePropertyAttribute on the inverseNavigation to verify that it matches.
            var inverseAttribute = inverseNavigationPropertyInfo.GetCustomAttribute <InversePropertyAttribute>(true);

            if (inverseAttribute != null &&
                inverseAttribute.Property != navigationPropertyInfo.Name)
            {
                throw new InvalidOperationException(
                          CoreStrings.InversePropertyMismatch(
                              navigationPropertyInfo.Name,
                              entityType.DisplayName(),
                              inverseNavigationPropertyInfo.Name,
                              targetEntityTypeBuilder.Metadata.DisplayName()));
            }

            var referencingNavigationsWithAttribute =
                AddInverseNavigation(entityType, navigationPropertyInfo, targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo);

            if (IsAmbiguousInverse(navigationPropertyInfo, entityType.ClrType, entityType.Model, referencingNavigationsWithAttribute))
            {
                var existingInverse     = targetEntityTypeBuilder.Metadata.FindNavigation(inverseNavigationPropertyInfo)?.FindInverse();
                var existingInverseType = existingInverse?.DeclaringEntityType.ClrType;
                if (existingInverse != null &&
                    IsAmbiguousInverse(
                        existingInverse.MemberInfo, existingInverseType, entityType.Model, referencingNavigationsWithAttribute))
                {
                    var fk = existingInverse.ForeignKey;
                    if (fk.GetConfigurationSource() == ConfigurationSource.DataAnnotation)
                    {
                        fk.DeclaringEntityType.Builder.RemoveForeignKey(fk, ConfigurationSource.DataAnnotation);
                    }
                }

                return(entityTypeBuilder.Metadata.FindNavigation(navigationPropertyInfo)?.ForeignKey.Builder);
            }

            return(targetEntityTypeBuilder.Relationship(
                       entityTypeBuilder,
                       inverseNavigationPropertyInfo,
                       navigationPropertyInfo,
                       ConfigurationSource.DataAnnotation));
        }
        private void CreateRelationships(
            IReadOnlyList <RelationshipCandidate> relationshipCandidates, InternalEntityTypeBuilder entityTypeBuilder)
        {
            var unusedEntityTypes = new List <EntityType>();

            foreach (var relationshipCandidate in relationshipCandidates)
            {
                Debug.Assert(relationshipCandidate.NavigationProperties.Count > 0);

                var entityType        = entityTypeBuilder.Metadata;
                var targetEntityType  = relationshipCandidate.TargetTypeBuilder.Metadata;
                var isAmbiguousOnBase = (entityType.BaseType != null &&
                                         HasAmbiguousNavigationsTo(
                                             entityType.BaseType, targetEntityType.ClrType)) ||
                                        (targetEntityType.BaseType != null &&
                                         HasAmbiguousNavigationsTo(
                                             targetEntityType.BaseType, entityType.ClrType));

                if ((relationshipCandidate.NavigationProperties.Count > 1 &&
                     relationshipCandidate.InverseProperties.Count > 0) ||
                    relationshipCandidate.InverseProperties.Count > 1 ||
                    isAmbiguousOnBase)
                {
                    if (!isAmbiguousOnBase)
                    {
                        AddAmbiguous(entityTypeBuilder, relationshipCandidate.NavigationProperties, targetEntityType.ClrType);

                        AddAmbiguous(relationshipCandidate.TargetTypeBuilder, relationshipCandidate.InverseProperties, entityType.ClrType);
                    }

                    foreach (var navigationProperty in relationshipCandidate.NavigationProperties)
                    {
                        var existingForeignKey = entityType.FindDeclaredNavigation(navigationProperty.Name)?.ForeignKey;
                        existingForeignKey?.DeclaringEntityType.Builder
                        .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                    }

                    foreach (var inverseProperty in relationshipCandidate.InverseProperties)
                    {
                        var existingForeignKey = targetEntityType.FindDeclaredNavigation(inverseProperty.Name)?.ForeignKey;
                        existingForeignKey?.DeclaringEntityType.Builder
                        .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                    }

                    unusedEntityTypes.Add(targetEntityType);

                    continue;
                }

                foreach (var navigation in relationshipCandidate.NavigationProperties)
                {
                    if (targetEntityType.Builder == null)
                    {
                        continue;
                    }

                    if (InversePropertyAttributeConvention.IsAmbiguous(entityType, navigation, targetEntityType))
                    {
                        unusedEntityTypes.Add(targetEntityType);
                        continue;
                    }

                    var inverse = relationshipCandidate.InverseProperties.SingleOrDefault();
                    if (inverse == null)
                    {
                        entityTypeBuilder.Navigation(
                            relationshipCandidate.TargetTypeBuilder,
                            navigation,
                            ConfigurationSource.Convention);
                    }
                    else
                    {
                        if (InversePropertyAttributeConvention.IsAmbiguous(targetEntityType, inverse, entityType))
                        {
                            unusedEntityTypes.Add(targetEntityType);
                            continue;
                        }
                        entityTypeBuilder.Relationship(
                            targetEntityType.Builder,
                            navigation,
                            inverse,
                            ConfigurationSource.Convention);
                    }
                }
            }

            foreach (var unusedEntityType in unusedEntityTypes)
            {
                if (unusedEntityType.HasDelegatedIdentity() &&
                    unusedEntityType.DefiningEntityType.FindNavigation(unusedEntityType.DefiningNavigationName) == null)
                {
                    entityTypeBuilder.ModelBuilder.
                    RemoveDelegatedIdentityEntityType(unusedEntityType, ConfigurationSource.Convention);
                }
            }
        }
예제 #6
0
        private InternalRelationshipBuilder ConfigureInverseNavigation(
            InternalEntityTypeBuilder entityTypeBuilder,
            MemberInfo navigationMemberInfo,
            InternalEntityTypeBuilder targetEntityTypeBuilder,
            InversePropertyAttribute attribute)
        {
            var entityType    = entityTypeBuilder.Metadata;
            var targetClrType = targetEntityTypeBuilder.Metadata.ClrType;
            var inverseNavigationPropertyInfo = targetClrType.GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, attribute.Property, StringComparison.OrdinalIgnoreCase));

            if (inverseNavigationPropertyInfo == null ||
                !FindCandidateNavigationPropertyType(inverseNavigationPropertyInfo).GetTypeInfo()
                .IsAssignableFrom(entityType.ClrType.GetTypeInfo()))
            {
                throw new InvalidOperationException(
                          CoreStrings.InvalidNavigationWithInverseProperty(
                              navigationMemberInfo.Name, entityType.DisplayName(), attribute.Property, targetClrType.ShortDisplayName()));
            }

            if (Equals(inverseNavigationPropertyInfo, navigationMemberInfo))
            {
                throw new InvalidOperationException(
                          CoreStrings.SelfReferencingNavigationWithInverseProperty(
                              navigationMemberInfo.Name,
                              entityType.DisplayName(),
                              navigationMemberInfo.Name,
                              entityType.DisplayName()));
            }

            // Check for InversePropertyAttribute on the inverseNavigation to verify that it matches.
            var inverseAttribute = inverseNavigationPropertyInfo.GetCustomAttribute <InversePropertyAttribute>(true);

            if (inverseAttribute != null &&
                inverseAttribute.Property != navigationMemberInfo.Name)
            {
                throw new InvalidOperationException(
                          CoreStrings.InversePropertyMismatch(
                              navigationMemberInfo.Name,
                              entityType.DisplayName(),
                              inverseNavigationPropertyInfo.Name,
                              targetEntityTypeBuilder.Metadata.DisplayName()));
            }

            var referencingNavigationsWithAttribute =
                AddInverseNavigation(entityType, navigationMemberInfo, targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo);

            if (IsAmbiguousInverse(navigationMemberInfo, entityType.ClrType, entityType.Model, referencingNavigationsWithAttribute))
            {
                var existingInverse     = targetEntityTypeBuilder.Metadata.FindNavigation(inverseNavigationPropertyInfo)?.FindInverse();
                var existingInverseType = existingInverse?.DeclaringEntityType.ClrType;
                if (existingInverse != null &&
                    IsAmbiguousInverse(
                        existingInverse.GetIdentifyingMemberInfo(), existingInverseType, entityType.Model, referencingNavigationsWithAttribute))
                {
                    var fk = existingInverse.ForeignKey;
                    fk.DeclaringEntityType.Builder.RemoveForeignKey(fk, ConfigurationSource.DataAnnotation);
                }

                var existingRelationship = entityTypeBuilder.Metadata.FindNavigation(navigationMemberInfo)?.ForeignKey;
                existingRelationship?.DeclaringEntityType.Builder.RemoveForeignKey(existingRelationship, ConfigurationSource.DataAnnotation);

                return(entityTypeBuilder.Metadata.FindNavigation(navigationMemberInfo)?.ForeignKey.Builder);
            }

            var ownership = entityType.FindOwnership();

            if (ownership != null &&
                ownership.PrincipalEntityType == targetEntityTypeBuilder.Metadata &&
                ownership.PrincipalToDependent?.GetIdentifyingMemberInfo() != inverseNavigationPropertyInfo)
            {
                _logger.NonOwnershipInverseNavigationWarning(entityType, navigationMemberInfo,
                                                             targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo,
                                                             ownership.PrincipalToDependent.GetIdentifyingMemberInfo());
                return(null);
            }

            if (entityType.DefiningEntityType == targetEntityTypeBuilder.Metadata &&
                entityType.DefiningNavigationName != inverseNavigationPropertyInfo.Name)
            {
                _logger.NonDefiningInverseNavigationWarning(entityType, navigationMemberInfo,
                                                            targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo,
                                                            targetClrType.GetRuntimeProperties().First(p => p.Name == entityType.DefiningNavigationName));
                return(null);
            }

            if (entityType.Model.ShouldBeOwnedType(entityType.ClrType) &&
                !entityType.IsInOwnershipPath(targetEntityTypeBuilder.Metadata))
            {
                return(targetEntityTypeBuilder.Owns(
                           entityTypeBuilder.Metadata.ClrType,
                           inverseNavigationPropertyInfo,
                           navigationMemberInfo,
                           ConfigurationSource.Convention));
            }

            return(targetEntityTypeBuilder.Relationship(
                       entityTypeBuilder,
                       inverseNavigationPropertyInfo,
                       navigationMemberInfo,
                       ConfigurationSource.DataAnnotation));
        }
예제 #7
0
        private static void CreateRelationships(
            IEnumerable <RelationshipCandidate> relationshipCandidates, InternalEntityTypeBuilder entityTypeBuilder)
        {
            var unusedEntityTypes = new List <EntityType>();

            foreach (var relationshipCandidate in relationshipCandidates)
            {
                var entityType        = entityTypeBuilder.Metadata;
                var targetEntityType  = relationshipCandidate.TargetTypeBuilder.Metadata;
                var isAmbiguousOnBase = entityType.BaseType != null &&
                                        HasAmbiguousNavigationsTo(
                    entityType.BaseType, targetEntityType.ClrType) ||
                                        targetEntityType.BaseType != null &&
                                        HasAmbiguousNavigationsTo(
                    targetEntityType.BaseType, entityType.ClrType);

                if (relationshipCandidate.NavigationProperties.Count > 1 &&
                    relationshipCandidate.InverseProperties.Count > 0 ||
                    relationshipCandidate.InverseProperties.Count > 1 ||
                    isAmbiguousOnBase)
                {
                    if (!isAmbiguousOnBase)
                    {
                        AddAmbiguous(entityTypeBuilder, relationshipCandidate.NavigationProperties, targetEntityType.ClrType);

                        AddAmbiguous(targetEntityType.Builder, relationshipCandidate.InverseProperties, entityType.ClrType);
                    }

                    foreach (var navigationProperty in relationshipCandidate.NavigationProperties)
                    {
                        var existingForeignKey = entityType.FindDeclaredNavigation(navigationProperty.Name)?.ForeignKey;
                        existingForeignKey?.DeclaringEntityType.Builder
                        .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                    }

                    foreach (var inverseProperty in relationshipCandidate.InverseProperties)
                    {
                        var existingForeignKey = targetEntityType.FindDeclaredNavigation(inverseProperty.Name)?.ForeignKey;
                        existingForeignKey?.DeclaringEntityType.Builder
                        .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                    }

                    unusedEntityTypes.Add(targetEntityType);

                    continue;
                }

                foreach (var navigation in relationshipCandidate.NavigationProperties)
                {
                    if (targetEntityType.Builder == null)
                    {
                        continue;
                    }

                    if (InversePropertyAttributeConvention.IsAmbiguous(entityType, navigation, targetEntityType))
                    {
                        unusedEntityTypes.Add(targetEntityType);
                        continue;
                    }

                    var inverse = relationshipCandidate.InverseProperties.SingleOrDefault();
                    if (inverse == null)
                    {
                        if (targetEntityType.DefiningNavigationName == navigation.Name &&
                            targetEntityType.DefiningEntityType == entityType &&
                            targetEntityType.Model.ShouldBeOwnedType(targetEntityType.ClrType))
                        {
                            entityTypeBuilder.Owns(
                                targetEntityType.ClrType,
                                navigation,
                                ConfigurationSource.Convention);
                        }
                        else
                        {
                            entityTypeBuilder.Navigation(
                                targetEntityType.Builder,
                                navigation,
                                ConfigurationSource.Convention);
                        }
                    }
                    else
                    {
                        if (InversePropertyAttributeConvention.IsAmbiguous(targetEntityType, inverse, entityType))
                        {
                            unusedEntityTypes.Add(targetEntityType);
                            continue;
                        }

                        if (targetEntityType.DefiningNavigationName == navigation.Name &&
                            targetEntityType.DefiningEntityType == entityType &&
                            targetEntityType.Model.ShouldBeOwnedType(targetEntityType.ClrType))
                        {
                            entityTypeBuilder.Owns(
                                targetEntityType.ClrType,
                                navigation,
                                inverse,
                                ConfigurationSource.Convention);
                        }
                        else
                        {
                            entityTypeBuilder.Relationship(
                                targetEntityType.Builder,
                                navigation,
                                inverse,
                                ConfigurationSource.Convention);
                        }
                    }
                }

                if (relationshipCandidate.NavigationProperties.Count == 0)
                {
                    foreach (var inverse in relationshipCandidate.InverseProperties)
                    {
                        if (targetEntityType.Builder == null)
                        {
                            continue;
                        }

                        if (InversePropertyAttributeConvention.IsAmbiguous(targetEntityType, inverse, entityType))
                        {
                            unusedEntityTypes.Add(targetEntityType);
                            continue;
                        }

                        targetEntityType.Builder.Navigation(
                            entityTypeBuilder,
                            inverse,
                            ConfigurationSource.Convention);
                    }
                }
            }

            foreach (var unusedEntityType in unusedEntityTypes)
            {
                if (unusedEntityType.HasDefiningNavigation() &&
                    unusedEntityType.DefiningEntityType.FindNavigation(unusedEntityType.DefiningNavigationName) == null)
                {
                    entityTypeBuilder.ModelBuilder.RemoveEntityType(unusedEntityType, ConfigurationSource.Convention);
                }
            }
        }
예제 #8
0
        private void CreateRelationships(
            IReadOnlyList <RelationshipCandidate> relationshipCandidates, InternalEntityTypeBuilder entityTypeBuilder)
        {
            foreach (var relationshipCandidate in relationshipCandidates)
            {
                Debug.Assert(relationshipCandidate.NavigationProperties.Count > 0);
                var isAmbiguousOnBase = (entityTypeBuilder.Metadata.BaseType != null &&
                                         HasAmbiguousNavigationsTo(
                                             entityTypeBuilder.Metadata.BaseType, relationshipCandidate.TargetTypeBuilder.Metadata.ClrType)) ||
                                        (relationshipCandidate.TargetTypeBuilder.Metadata.BaseType != null &&
                                         HasAmbiguousNavigationsTo(
                                             relationshipCandidate.TargetTypeBuilder.Metadata.BaseType, entityTypeBuilder.Metadata.ClrType));

                if ((relationshipCandidate.NavigationProperties.Count > 1 &&
                     relationshipCandidate.InverseProperties.Count > 0) ||
                    relationshipCandidate.InverseProperties.Count > 1 ||
                    isAmbiguousOnBase)
                {
                    if (!isAmbiguousOnBase)
                    {
                        AddAmbiguous(entityTypeBuilder, relationshipCandidate.NavigationProperties, relationshipCandidate.TargetTypeBuilder.Metadata.ClrType);

                        AddAmbiguous(relationshipCandidate.TargetTypeBuilder, relationshipCandidate.InverseProperties, entityTypeBuilder.Metadata.ClrType);
                    }

                    foreach (var navigationProperty in relationshipCandidate.NavigationProperties)
                    {
                        var existingForeignKey = entityTypeBuilder.Metadata.FindDeclaredNavigation(navigationProperty.Name)?.ForeignKey;
                        existingForeignKey?.DeclaringEntityType.Builder
                        .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                    }

                    foreach (var inverseProperty in relationshipCandidate.InverseProperties)
                    {
                        var existingForeignKey = relationshipCandidate.TargetTypeBuilder.Metadata
                                                 .FindDeclaredNavigation(inverseProperty.Name)?.ForeignKey;
                        existingForeignKey?.DeclaringEntityType.Builder
                        .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                    }

                    continue;
                }

                foreach (var navigation in relationshipCandidate.NavigationProperties)
                {
                    var inverse = relationshipCandidate.InverseProperties.SingleOrDefault();
                    if (inverse == null)
                    {
                        entityTypeBuilder.Navigation(
                            relationshipCandidate.TargetTypeBuilder,
                            navigation,
                            ConfigurationSource.Convention);
                    }
                    else
                    {
                        entityTypeBuilder.Relationship(
                            relationshipCandidate.TargetTypeBuilder,
                            navigation,
                            inverse,
                            ConfigurationSource.Convention);
                    }
                }
            }
        }
        private void CreateRelationships(
            IReadOnlyList<RelationshipCandidate> relationshipCandidates, InternalEntityTypeBuilder entityTypeBuilder)
        {
            foreach (var relationshipCandidate in relationshipCandidates)
            {
                if ((relationshipCandidate.NavigationProperties.Count > 1
                     && relationshipCandidate.InverseProperties.Count > 0)
                    || relationshipCandidate.InverseProperties.Count > 1)
                {
                    foreach (var navigationProperty in relationshipCandidate.NavigationProperties)
                    {
                        var existingForeignKey = entityTypeBuilder.Metadata.FindDeclaredNavigation(navigationProperty.Name)?.ForeignKey;
                        if (existingForeignKey != null)
                        {
                            entityTypeBuilder.ModelBuilder.Entity(existingForeignKey.DeclaringEntityType.Name, ConfigurationSource.Convention)
                                .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                        }
                    }

                    foreach (var inverseProperty in relationshipCandidate.InverseProperties)
                    {
                        var existingForeignKey = relationshipCandidate.TargetTypeBuilder.Metadata.FindDeclaredNavigation(inverseProperty.Name)?.ForeignKey;
                        if (existingForeignKey != null)
                        {
                            entityTypeBuilder.ModelBuilder.Entity(existingForeignKey.DeclaringEntityType.Name, ConfigurationSource.Convention)
                                .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention);
                        }
                    }

                    break;
                }

                foreach (var navigation in relationshipCandidate.NavigationProperties)
                {
                    var inverse = relationshipCandidate.InverseProperties.SingleOrDefault();
                    entityTypeBuilder.Relationship(
                        relationshipCandidate.TargetTypeBuilder,
                        navigation,
                        inverse,
                        ConfigurationSource.Convention);
                }
            }
        }