Exemplo n.º 1
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));
        }