public virtual void Ambiguous_relationship_between_owned_types_throws()
            {
                var modelBuilder = CreateModelBuilder();

                modelBuilder.Owned <Order>();
                modelBuilder.Entity <SpecialCustomer>().OwnsMany(c => c.SpecialOrders);

                Assert.Equal(CoreStrings.AmbiguousOwnedNavigation(nameof(SpecialOrder), nameof(BackOrder)),
                             Assert.Throws <InvalidOperationException>(() => modelBuilder.Validate()).Message);
            }
            public virtual void Ambiguous_relationship_between_owned_types_throws()
            {
                var modelBuilder = CreateModelBuilder();

                modelBuilder.Owned <Whoopper>();
                modelBuilder.Owned <Moostard>();
                modelBuilder.Entity <ToastedBun>();

                Assert.Equal(CoreStrings.AmbiguousOwnedNavigation(nameof(Moostard), nameof(Whoopper)),
                             Assert.Throws <InvalidOperationException>(() => modelBuilder.Validate()).Message);
            }
        /// <summary>
        ///     Validates property mappings.
        /// </summary>
        /// <param name="model"> The model. </param>
        /// <param name="logger"> The logger to use. </param>
        protected virtual void ValidatePropertyMapping([NotNull] IModel model, [NotNull] IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
        {
            Check.NotNull(model, nameof(model));

            if (!(model is IConventionModel conventionModel))
            {
                return;
            }

            foreach (var entityType in conventionModel.GetEntityTypes())
            {
                var unmappedProperty = entityType.GetProperties().FirstOrDefault(
                    p => (!ConfigurationSource.Convention.Overrides(p.GetConfigurationSource()) ||
                          !p.IsShadowProperty()) &&
                    !IsMappedPrimitiveProperty(p));

                if (unmappedProperty != null)
                {
                    throw new InvalidOperationException(
                              CoreStrings.PropertyNotMapped(
                                  entityType.DisplayName(), unmappedProperty.Name, unmappedProperty.ClrType.ShortDisplayName()));
                }

                if (!entityType.HasClrType())
                {
                    continue;
                }

                var clrProperties = new HashSet <string>(StringComparer.Ordinal);

                var runtimeProperties = entityType.AsEntityType().GetRuntimeProperties();

                clrProperties.UnionWith(
                    runtimeProperties.Values
                    .Where(pi => pi.IsCandidateProperty())
                    .Select(pi => pi.GetSimpleMemberName()));

                clrProperties.ExceptWith(entityType.GetProperties().Select(p => p.Name));
                clrProperties.ExceptWith(entityType.GetNavigations().Select(p => p.Name));
                clrProperties.ExceptWith(entityType.GetServiceProperties().Select(p => p.Name));
                clrProperties.RemoveWhere(p => entityType.FindIgnoredConfigurationSource(p) != null);

                if (clrProperties.Count <= 0)
                {
                    continue;
                }

                foreach (var clrProperty in clrProperties)
                {
                    var actualProperty     = runtimeProperties[clrProperty];
                    var propertyType       = actualProperty.PropertyType;
                    var targetSequenceType = propertyType.TryGetSequenceType();

                    if (conventionModel.FindIgnoredConfigurationSource(propertyType.DisplayName()) != null ||
                        targetSequenceType != null &&
                        conventionModel.FindIgnoredConfigurationSource(targetSequenceType.DisplayName()) != null)
                    {
                        continue;
                    }

                    var targetType = FindCandidateNavigationPropertyType(actualProperty);

                    var isTargetWeakOrOwned
                        = targetType != null &&
                          (conventionModel.HasEntityTypeWithDefiningNavigation(targetType) ||
                           conventionModel.IsOwned(targetType));

                    if (targetType?.IsValidEntityType() == true &&
                        (isTargetWeakOrOwned ||
                         conventionModel.FindEntityType(targetType) != null ||
                         targetType.GetRuntimeProperties().Any(p => p.IsCandidateProperty())))
                    {
                        // ReSharper disable CheckForReferenceEqualityInstead.1
                        // ReSharper disable CheckForReferenceEqualityInstead.3
                        if ((!entityType.IsKeyless ||
                             targetSequenceType == null) &&
                            entityType.GetDerivedTypes().All(
                                dt => dt.GetDeclaredNavigations().FirstOrDefault(n => n.Name == actualProperty.GetSimpleMemberName()) == null) &&
                            (!isTargetWeakOrOwned ||
                             (!targetType.Equals(entityType.ClrType) &&
                              (!entityType.IsInOwnershipPath(targetType) ||
                               (entityType.FindOwnership().PrincipalEntityType.ClrType.Equals(targetType) &&
                                targetSequenceType == null)) &&
                              (!entityType.IsInDefinitionPath(targetType) ||
                               (entityType.DefiningEntityType.ClrType.Equals(targetType) &&
                                targetSequenceType == null)))))
                        {
                            if (conventionModel.IsOwned(entityType.ClrType) &&
                                conventionModel.IsOwned(targetType))
                            {
                                throw new InvalidOperationException(
                                          CoreStrings.AmbiguousOwnedNavigation(entityType.DisplayName(), targetType.ShortDisplayName()));
                            }

                            throw new InvalidOperationException(
                                      CoreStrings.NavigationNotAdded(
                                          entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
                        }
                        // ReSharper restore CheckForReferenceEqualityInstead.3
                        // ReSharper restore CheckForReferenceEqualityInstead.1
                    }
                    else if (targetSequenceType == null && propertyType.GetTypeInfo().IsInterface ||
                             targetSequenceType?.GetTypeInfo().IsInterface == true)
                    {
                        throw new InvalidOperationException(
                                  CoreStrings.InterfacePropertyNotAdded(
                                      entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
                    }
                    else
                    {
                        throw new InvalidOperationException(
                                  CoreStrings.PropertyNotAdded(
                                      entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual InternalModelBuilder Apply(InternalModelBuilder modelBuilder)
        {
            foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
            {
                var unmappedProperty = entityType.GetProperties().FirstOrDefault(
                    p => (!ConfigurationSource.Convention.Overrides(p.GetConfigurationSource()) || !p.IsShadowProperty) &&
                    !IsMappedPrimitiveProperty(p));

                if (unmappedProperty != null)
                {
                    throw new InvalidOperationException(
                              CoreStrings.PropertyNotMapped(
                                  entityType.DisplayName(), unmappedProperty.Name, unmappedProperty.ClrType.ShortDisplayName()));
                }

                if (!entityType.HasClrType())
                {
                    continue;
                }

                var clrProperties = new HashSet <string>(StringComparer.Ordinal);

                clrProperties.UnionWith(
                    entityType.GetRuntimeProperties().Values
                    .Where(pi => pi.IsCandidateProperty())
                    .Select(pi => pi.GetSimpleMemberName()));

                clrProperties.ExceptWith(entityType.GetProperties().Select(p => p.Name));
                clrProperties.ExceptWith(entityType.GetNavigations().Select(p => p.Name));
                clrProperties.ExceptWith(entityType.GetServiceProperties().Select(p => p.Name));
                clrProperties.RemoveWhere(p => entityType.Builder.IsIgnored(p, ConfigurationSource.Convention));

                if (clrProperties.Count <= 0)
                {
                    continue;
                }

                foreach (var clrProperty in clrProperties)
                {
                    var actualProperty     = entityType.GetRuntimeProperties()[clrProperty];
                    var propertyType       = actualProperty.PropertyType;
                    var targetSequenceType = propertyType.TryGetSequenceType();

                    if (modelBuilder.IsIgnored(
                            modelBuilder.Metadata.GetDisplayName(propertyType),
                            ConfigurationSource.Convention) ||
                        (targetSequenceType != null &&
                         modelBuilder.IsIgnored(
                             modelBuilder.Metadata.GetDisplayName(targetSequenceType),
                             ConfigurationSource.Convention)))
                    {
                        continue;
                    }

                    var targetType = FindCandidateNavigationPropertyType(actualProperty);

                    var isTargetWeakOrOwned
                        = targetType != null &&
                          (modelBuilder.Metadata.HasEntityTypeWithDefiningNavigation(targetType) ||
                           modelBuilder.Metadata.ShouldBeOwnedType(targetType));

                    if (targetType?.IsValidEntityType() == true &&
                        (isTargetWeakOrOwned ||
                         modelBuilder.Metadata.FindEntityType(targetType) != null ||
                         targetType.GetRuntimeProperties().Any(p => p.IsCandidateProperty())))
                    {
                        // ReSharper disable CheckForReferenceEqualityInstead.1
                        // ReSharper disable CheckForReferenceEqualityInstead.3
                        if ((!entityType.IsQueryType ||
                             targetSequenceType == null) &&
                            entityType.GetDerivedTypes().All(
                                dt => dt.FindDeclaredNavigation(actualProperty.GetSimpleMemberName()) == null) &&
                            (!isTargetWeakOrOwned ||
                             (!targetType.Equals(entityType.ClrType) &&
                              (!entityType.IsInOwnershipPath(targetType) ||
                               (entityType.FindOwnership().PrincipalEntityType.ClrType.Equals(targetType) &&
                                targetSequenceType == null)) &&
                              (!entityType.IsInDefinitionPath(targetType) ||
                               (entityType.DefiningEntityType.ClrType.Equals(targetType) &&
                                targetSequenceType == null)))))
                        {
                            if (modelBuilder.Metadata.ShouldBeOwnedType(entityType.ClrType) &&
                                modelBuilder.Metadata.ShouldBeOwnedType(targetType))
                            {
                                throw new InvalidOperationException(
                                          CoreStrings.AmbiguousOwnedNavigation(entityType.DisplayName(), targetType.ShortDisplayName()));
                            }

                            throw new InvalidOperationException(
                                      CoreStrings.NavigationNotAdded(
                                          entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
                        }
                        // ReSharper restore CheckForReferenceEqualityInstead.3
                        // ReSharper restore CheckForReferenceEqualityInstead.1
                    }
                    else if (targetSequenceType == null && propertyType.GetTypeInfo().IsInterface ||
                             targetSequenceType?.GetTypeInfo().IsInterface == true)
                    {
                        throw new InvalidOperationException(
                                  CoreStrings.InterfacePropertyNotAdded(
                                      entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
                    }
                    else
                    {
                        throw new InvalidOperationException(
                                  CoreStrings.PropertyNotAdded(
                                      entityType.DisplayName(), actualProperty.Name, propertyType.ShortDisplayName()));
                    }
                }
            }

            return(modelBuilder);
        }
예제 #5
0
    /// <summary>
    ///     Validates property mappings.
    /// </summary>
    /// <param name="model">The model.</param>
    /// <param name="logger">The logger to use.</param>
    protected virtual void ValidatePropertyMapping(
        IModel model,
        IDiagnosticsLogger <DbLoggerCategory.Model.Validation> logger)
    {
        if (model is not IConventionModel conventionModel)
        {
            return;
        }

        foreach (var entityType in conventionModel.GetEntityTypes())
        {
            var unmappedProperty = entityType.GetDeclaredProperties().FirstOrDefault(
                p => (!ConfigurationSource.Convention.Overrides(p.GetConfigurationSource())
                      // Use a better condition for non-persisted properties when issue #14121 is implemented
                      || !p.IsImplicitlyCreated()) &&
                p.FindTypeMapping() == null);

            if (unmappedProperty != null)
            {
                ThrowPropertyNotMappedException(
                    (unmappedProperty.GetValueConverter()?.ProviderClrType ?? unmappedProperty.ClrType).ShortDisplayName(),
                    entityType,
                    unmappedProperty);
            }

            if (entityType.ClrType == Model.DefaultPropertyBagType)
            {
                continue;
            }

            var runtimeProperties = entityType.GetRuntimeProperties();
            var clrProperties     = new HashSet <string>(StringComparer.Ordinal);
            clrProperties.UnionWith(
                runtimeProperties.Values
                .Where(pi => pi.IsCandidateProperty(needsWrite: false))
                .Select(pi => pi.GetSimpleMemberName()));

            clrProperties.ExceptWith(
                ((IEnumerable <IConventionPropertyBase>)entityType.GetProperties())
                .Concat(entityType.GetNavigations())
                .Concat(entityType.GetSkipNavigations())
                .Concat(entityType.GetServiceProperties()).Select(p => p.Name));

            if (entityType.IsPropertyBag)
            {
                clrProperties.ExceptWith(_dictionaryProperties);
            }

            if (clrProperties.Count <= 0)
            {
                continue;
            }

            foreach (var clrPropertyName in clrProperties)
            {
                if (entityType.FindIgnoredConfigurationSource(clrPropertyName) != null)
                {
                    continue;
                }

                var clrProperty        = runtimeProperties[clrPropertyName];
                var propertyType       = clrProperty.PropertyType;
                var targetSequenceType = propertyType.TryGetSequenceType();

                if (conventionModel.FindIgnoredConfigurationSource(propertyType) != null ||
                    conventionModel.IsIgnoredType(propertyType) ||
                    (targetSequenceType != null &&
                     (conventionModel.FindIgnoredConfigurationSource(targetSequenceType) != null ||
                      conventionModel.IsIgnoredType(targetSequenceType))))
                {
                    continue;
                }

                var targetType = Dependencies.MemberClassifier.FindCandidateNavigationPropertyType(
                    clrProperty, conventionModel, out var targetOwned);
                if (targetType == null &&
                    clrProperty.FindSetterProperty() == null)
                {
                    continue;
                }

                if (targetType != null)
                {
                    var targetShared = conventionModel.IsShared(targetType);
                    targetOwned ??= IsOwned(targetType, conventionModel);
                    // ReSharper disable CheckForReferenceEqualityInstead.1
                    // ReSharper disable CheckForReferenceEqualityInstead.3
                    if ((!entityType.IsKeyless ||
                         targetSequenceType == null) &&
                        entityType.GetDerivedTypes().All(
                            dt => dt.GetDeclaredNavigations().FirstOrDefault(n => n.Name == clrProperty.GetSimpleMemberName())
                            == null) &&
                        (!(targetShared || targetOwned.Value) ||
                         !targetType.Equals(entityType.ClrType)) &&
                        (!entityType.IsInOwnershipPath(targetType) ||
                         targetSequenceType == null))
                    {
                        if (entityType.IsOwned() &&
                            targetOwned.Value)
                        {
                            throw new InvalidOperationException(
                                      CoreStrings.AmbiguousOwnedNavigation(
                                          entityType.DisplayName() + "." + clrProperty.Name, targetType.ShortDisplayName()));
                        }

                        if (targetShared)
                        {
                            throw new InvalidOperationException(
                                      CoreStrings.NonConfiguredNavigationToSharedType(clrProperty.Name, entityType.DisplayName()));
                        }

                        throw new InvalidOperationException(
                                  CoreStrings.NavigationNotAdded(
                                      entityType.DisplayName(), clrProperty.Name, propertyType.ShortDisplayName()));
                    }

                    // ReSharper restore CheckForReferenceEqualityInstead.3
                    // ReSharper restore CheckForReferenceEqualityInstead.1
                }
                else if (targetSequenceType == null && propertyType.IsInterface ||
                         targetSequenceType?.IsInterface == true)
                {
                    throw new InvalidOperationException(
                              CoreStrings.InterfacePropertyNotAdded(
                                  entityType.DisplayName(), clrProperty.Name, propertyType.ShortDisplayName()));
                }
                else
                {
                    throw new InvalidOperationException(
                              CoreStrings.PropertyNotAdded(
                                  entityType.DisplayName(), clrProperty.Name, propertyType.ShortDisplayName()));
                }
            }
        }
    }