Example #1
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);
        }