private static ForeignKey?CreateSkipNavigationForeignKey(
     SkipNavigation skipNavigation,
     InternalEntityTypeBuilder joinEntityTypeBuilder)
 => joinEntityTypeBuilder
 .HasRelationship(
     skipNavigation.DeclaringEntityType,
     ConfigurationSource.Convention,
     required: true,
     skipNavigation.Inverse !.Name) !
Exemplo n.º 2
0
 private static ForeignKey CreateSkipNavigationForeignKey(
     SkipNavigation skipNavigation,
     InternalEntityTypeBuilder joinEntityTypeBuilder)
 => joinEntityTypeBuilder
 .HasRelationship(
     skipNavigation.DeclaringEntityType,
     ConfigurationSource.Convention,
     required: true)
 .IsUnique(false, ConfigurationSource.Convention)
 .Metadata;
Exemplo n.º 3
0
        private static ForeignKey CreateSkipNavigationForeignKey(
            SkipNavigation skipNavigation,
            InternalEntityTypeBuilder associationEntityTypeBuilder)
        {
            var principalEntityType = skipNavigation.DeclaringEntityType;
            var principalKey        = principalEntityType.FindPrimaryKey();

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

            var dependentEndForeignKeyPropertyNames = new List <string>();
            var otherIdentifiers = associationEntityTypeBuilder.Metadata
                                   .GetDeclaredProperties().ToDictionary(p => p.Name, p => 0);

            foreach (var property in principalKey.Properties)
            {
                var propertyName = Uniquifier.Uniquify(
                    string.Format(
                        AssociationPropertyNameTemplate,
                        principalEntityType.ShortName(),
                        property.Name),
                    otherIdentifiers,
                    int.MaxValue);
                dependentEndForeignKeyPropertyNames.Add(propertyName);
                otherIdentifiers.Add(propertyName, 0);
            }

            return(associationEntityTypeBuilder
                   .HasRelationship(
                       principalEntityType.Name,
                       dependentEndForeignKeyPropertyNames,
                       principalKey,
                       ConfigurationSource.Convention)
                   .IsUnique(false, ConfigurationSource.Convention)
                   .Metadata);
        }
Exemplo n.º 4
0
        private InternalRelationshipBuilder ConfigureInverseNavigation(
            InternalEntityTypeBuilder entityTypeBuilder,
            MemberInfo navigationMemberInfo,
            InternalEntityTypeBuilder targetEntityTypeBuilder,
            InversePropertyAttribute attribute)
        {
            var entityType    = entityTypeBuilder.Metadata;
            var targetClrType = targetEntityTypeBuilder.Metadata.ClrType;
            var inverseNavigationPropertyInfo = targetEntityTypeBuilder.Metadata.GetRuntimeProperties().Values
                                                .FirstOrDefault(p => string.Equals(p.GetSimpleMemberName(), 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.
            if (Attribute.IsDefined(inverseNavigationPropertyInfo, typeof(InversePropertyAttribute)))
            {
                var inverseAttribute = inverseNavigationPropertyInfo.GetCustomAttribute <InversePropertyAttribute>(true);
                if (inverseAttribute.Property != navigationMemberInfo.GetSimpleMemberName())
                {
                    throw new InvalidOperationException(
                              CoreStrings.InversePropertyMismatch(
                                  navigationMemberInfo.Name,
                                  entityType.DisplayName(),
                                  inverseNavigationPropertyInfo.Name,
                                  targetEntityTypeBuilder.Metadata.DisplayName()));
                }
            }

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

            var ambiguousInverse = FindAmbiguousInverse(
                navigationMemberInfo, entityType, entityType.Model, referencingNavigationsWithAttribute);

            if (ambiguousInverse != null)
            {
                var existingInverse     = targetEntityTypeBuilder.Metadata.FindNavigation(inverseNavigationPropertyInfo)?.FindInverse();
                var existingInverseType = existingInverse?.DeclaringEntityType;
                if (existingInverse != null &&
                    IsAmbiguousInverse(
                        existingInverse.GetIdentifyingMemberInfo(), existingInverseType, entityType.Model,
                        referencingNavigationsWithAttribute))
                {
                    var fk = existingInverse.ForeignKey;
                    if (fk.IsOwnership ||
                        fk.DeclaringEntityType.Builder.RemoveForeignKey(fk, ConfigurationSource.DataAnnotation) == null)
                    {
                        fk.Builder.HasNavigations(
                            existingInverse.IsDependentToPrincipal() ? PropertyIdentity.None : (PropertyIdentity?)null,
                            existingInverse.IsDependentToPrincipal() ? (PropertyIdentity?)null : PropertyIdentity.None,
                            ConfigurationSource.DataAnnotation);
                    }
                }

                var existingNavigation = entityType.FindNavigation(navigationMemberInfo);
                if (existingNavigation != null)
                {
                    var fk = existingNavigation.ForeignKey;
                    if (fk.IsOwnership ||
                        fk.DeclaringEntityType.Builder.RemoveForeignKey(fk, ConfigurationSource.DataAnnotation) == null)
                    {
                        fk.Builder.HasNavigations(
                            existingNavigation.IsDependentToPrincipal() ? PropertyIdentity.None : (PropertyIdentity?)null,
                            existingNavigation.IsDependentToPrincipal() ? (PropertyIdentity?)null : PropertyIdentity.None,
                            ConfigurationSource.DataAnnotation);
                    }
                }

                var existingAmbiguousNavigation = entityType.Model.FindActualEntityType(ambiguousInverse.Value.Item2)
                                                  .FindNavigation(ambiguousInverse.Value.Item1);
                if (existingAmbiguousNavigation != null)
                {
                    var fk = existingAmbiguousNavigation.ForeignKey;
                    if (fk.IsOwnership ||
                        fk.DeclaringEntityType.Builder.RemoveForeignKey(fk, ConfigurationSource.DataAnnotation) == null)
                    {
                        fk.Builder.HasNavigations(
                            existingAmbiguousNavigation.IsDependentToPrincipal() ? PropertyIdentity.None : (PropertyIdentity?)null,
                            existingAmbiguousNavigation.IsDependentToPrincipal() ? (PropertyIdentity?)null : PropertyIdentity.None,
                            ConfigurationSource.DataAnnotation);
                    }
                }

                return(entityType.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 != null &&
                entityType.DefiningEntityType == targetEntityTypeBuilder.Metadata &&
                entityType.DefiningNavigationName != inverseNavigationPropertyInfo.GetSimpleMemberName())
            {
                Logger.NonDefiningInverseNavigationWarning(
                    entityType, navigationMemberInfo,
                    targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo,
                    entityType.DefiningEntityType.GetRuntimeProperties()[entityType.DefiningNavigationName]);
                return(null);
            }

            return(entityType.Model.ShouldBeOwned(entityType.ClrType) &&
                   !entityType.IsInOwnershipPath(targetEntityTypeBuilder.Metadata)
                ? targetEntityTypeBuilder.HasOwnership(
                       entityTypeBuilder.Metadata.ClrType,
                       inverseNavigationPropertyInfo,
                       navigationMemberInfo,
                       ConfigurationSource.Convention)
                : targetEntityTypeBuilder.HasRelationship(
                       entityType,
                       inverseNavigationPropertyInfo,
                       navigationMemberInfo,
                       ConfigurationSource.DataAnnotation));
        }