Exemplo n.º 1
0
        public virtual void Apply(InternalEntityTypeBuilder entityTypeBuilder, ForeignKey foreignKey)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            Check.NotNull(foreignKey, nameof(foreignKey));

            ConfigureKeyProperties(entityTypeBuilder, foreignKey.Properties);
        }
Exemplo n.º 2
0
        public virtual void Apply(InternalEntityTypeBuilder entityTypeBuilder, ForeignKey foreignKey)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            Check.NotNull(foreignKey, nameof(foreignKey));

            SetValueGeneration(entityTypeBuilder, foreignKey.Properties);
            SetIdentity(entityTypeBuilder, foreignKey.Properties);
        }
        private IReadOnlyList<RelationshipCandidate> FindRelationshipCandidates(InternalEntityTypeBuilder entityTypeBuilder)
        {
            var entityType = entityTypeBuilder.Metadata;
            var relationshipCandidates = new Dictionary<Type, RelationshipCandidate>();
            foreach (var navigationPropertyInfo in entityType.ClrType.GetRuntimeProperties().OrderBy(p => p.Name))
            {
                var targetClrType = FindCandidateNavigationPropertyType(navigationPropertyInfo);
                var navigationName = navigationPropertyInfo.Name;
                if (targetClrType == null
                    || entityTypeBuilder.IsIgnored(navigationName, configurationSource: ConfigurationSource.Convention))
                {
                    continue;
                }

                var candidateTargetEntityTypeBuilder = entityTypeBuilder.ModelBuilder.Entity(targetClrType, ConfigurationSource.Convention);
                if (candidateTargetEntityTypeBuilder == null)
                {
                    continue;
                }

                RelationshipCandidate existingCandidate;
                if (relationshipCandidates.TryGetValue(candidateTargetEntityTypeBuilder.Metadata.ClrType, out existingCandidate))
                {
                    if (candidateTargetEntityTypeBuilder.Metadata != entityType
                        || !existingCandidate.InverseProperties.Contains(navigationPropertyInfo))
                    {
                        existingCandidate.NavigationProperties.Add(navigationPropertyInfo);
                    }

                    continue;
                }

                var navigations = new HashSet<PropertyInfo> { navigationPropertyInfo };
                var inverseNavigationCandidates = new HashSet<PropertyInfo>();
                foreach (var inversePropertyInfo in candidateTargetEntityTypeBuilder.Metadata.ClrType.GetRuntimeProperties().OrderBy(p => p.Name))
                {
                    var inverseTargetType = FindCandidateNavigationPropertyType(inversePropertyInfo);
                    if (inverseTargetType == null
                        || !inverseTargetType.GetTypeInfo().IsAssignableFrom(entityType.ClrType.GetTypeInfo())
                        || navigationPropertyInfo == inversePropertyInfo
                        || candidateTargetEntityTypeBuilder.IsIgnored(inversePropertyInfo.Name, ConfigurationSource.Convention))
                    {
                        continue;
                    }

                    inverseNavigationCandidates.Add(inversePropertyInfo);
                }

                relationshipCandidates[candidateTargetEntityTypeBuilder.Metadata.ClrType] =
                    new RelationshipCandidate(candidateTargetEntityTypeBuilder, navigations, inverseNavigationCandidates);
            }

            return relationshipCandidates.Values.ToList();
        }
        /// <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 InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            var entityType = entityTypeBuilder.Metadata;
            var clrType = entityType.ClrType;
            if (clrType == null)
            {
                return entityTypeBuilder;
            }

            var baseEntityType = FindClosestBaseType(entityType);
            return entityTypeBuilder.HasBaseType(baseEntityType, ConfigurationSource.Convention);
        }
        public virtual void Apply(InternalEntityTypeBuilder entityTypeBuilder, ForeignKey foreignKey)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            Check.NotNull(foreignKey, nameof(foreignKey));

            var properties = foreignKey.Properties;

            if (properties.Any(e => e.GenerateValueOnAdd == true))
            {
                ConfigureValueGenerationStrategy(entityTypeBuilder, properties, true);
            }
        }
Exemplo n.º 6
0
        public virtual void Apply(InternalEntityTypeBuilder entityTypeBuilder, ForeignKey foreignKey)
        {
            var properties = foreignKey.Properties;
            SetValueGeneration(entityTypeBuilder, properties);

            var valueGeneratedOnAddProperty = FindValueGeneratedOnAddProperty(properties);
            if (valueGeneratedOnAddProperty != null
                && entityTypeBuilder.Metadata.FindPrimaryKey(properties) != null)
            {
                SetIdentity(entityTypeBuilder, valueGeneratedOnAddProperty);
            }
        }
        public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            var entityType = entityTypeBuilder.Metadata;

            var keyProperties = DiscoverKeyProperties(entityType);
            if (keyProperties.Count != 0)
            {
                entityTypeBuilder.PrimaryKey(keyProperties.Select(p => p.Name).ToList(), ConfigurationSource.Convention);
            }

            return entityTypeBuilder;
        }
Exemplo n.º 8
0
 private void SetValueGeneration(InternalEntityTypeBuilder entityTypeBuilder, IEnumerable<Property> properties)
 {
     var propertyBuilders = InternalEntityTypeBuilder.GetPropertyBuilders(
         entityTypeBuilder.ModelBuilder,
         properties.Where(property =>
             !entityTypeBuilder.Metadata.GetForeignKeys().SelectMany(fk => fk.Properties).Contains(property)
             && ((IProperty)property).ValueGenerated == ValueGenerated.OnAdd),
         ConfigurationSource.Convention);
     foreach (var propertyBuilder in propertyBuilders)
     {
         propertyBuilder?.UseValueGenerator(true, ConfigurationSource.Convention);
     }
 }
        /// <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 bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityType oldBaseType)
        {
            if (oldBaseType != null
                && oldBaseType.BaseType == null
                && !oldBaseType.GetDerivedTypes().Any())
            {
                var oldBaseTypeBuilder = oldBaseType.Builder;
                oldBaseTypeBuilder?.Relational(ConfigurationSource.Convention).HasDiscriminator(propertyInfo: null);
            }

            var entityType = entityTypeBuilder.Metadata;
            var derivedEntityTypes = entityType.GetDerivedTypes().ToList();

            DiscriminatorBuilder discriminator;
            if (entityType.BaseType == null)
            {
                if (!derivedEntityTypes.Any())
                {
                    entityTypeBuilder.Relational(ConfigurationSource.Convention).HasDiscriminator(propertyInfo: null);
                    return true;
                }

                discriminator = entityTypeBuilder.Relational(ConfigurationSource.Convention)
                    .HasDiscriminator(typeof(string));
            }
            else
            {
                if (entityTypeBuilder.Relational(ConfigurationSource.Convention).HasDiscriminator(propertyInfo: null) == null)
                {
                    // TODO: log warning that the current discriminator couldn't be removed
                    return true;
                }

                var rootTypeBuilder = entityType.RootType().Builder;
                discriminator = rootTypeBuilder?.Relational(ConfigurationSource.Convention).HasDiscriminator(typeof(string));

                if (entityType.BaseType.BaseType == null)
                {
                    discriminator?.HasValue(entityType.BaseType.Name, entityType.BaseType.DisplayName());
                }
            }

            if (discriminator != null)
            {
                discriminator.HasValue(entityTypeBuilder.Metadata.Name, entityTypeBuilder.Metadata.DisplayName());
                SetDefaultDiscriminatorValues(derivedEntityTypes, discriminator);
            }

            return true;
        }
        public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));

            if (!entityTypeBuilder.Metadata.HasClrType())
            {
                return entityTypeBuilder;
            }

            var relationshipCandidates = FindRelationshipCandidates(entityTypeBuilder);
            relationshipCandidates = RemoveIncompatibleWithExistingRelationships(relationshipCandidates, entityTypeBuilder);
            relationshipCandidates = RemoveInheritedInverseNavigations(relationshipCandidates);
            CreateRelationships(relationshipCandidates, entityTypeBuilder);

            return entityTypeBuilder;
        }
        public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            var entityType = entityTypeBuilder.Metadata;

            if (entityType.HasClrType)
            {
                var primitiveProperties = entityType.ClrType.GetRuntimeProperties().Where(IsCandidatePrimitiveProperty);
                foreach (var propertyInfo in primitiveProperties)
                {
                    entityTypeBuilder.Property(propertyInfo, ConfigurationSource.Convention);
                }
            }

            return entityTypeBuilder;
        }
        public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            var entityType = entityTypeBuilder.Metadata;

            if (entityType.BaseType == null)
            {
                var candidateProperties = entityType.GetProperties().Where(p => !((IProperty)p).IsShadowProperty || !entityTypeBuilder.CanRemoveProperty(p, ConfigurationSource.Convention)).ToList();
                var keyProperties = DiscoverKeyProperties(entityType, candidateProperties);
                if (keyProperties.Count != 0)
                {
                    entityTypeBuilder.PrimaryKey(keyProperties.Select(p => p.Name).ToList(), ConfigurationSource.Convention);
                }
            }

            return entityTypeBuilder;
        }
        public void OnEntityTypeAdded_calls_apply_on_conventions_in_order(bool useBuilder)
        {
            var conventions = new ConventionSet();

            InternalEntityTypeBuilder entityTypeBuilder = null;
            var convention = new Mock<IEntityTypeConvention>();
            convention.Setup(c => c.Apply(It.IsAny<InternalEntityTypeBuilder>())).Returns<InternalEntityTypeBuilder>(b =>
                {
                    Assert.NotNull(b);
                    entityTypeBuilder = new InternalEntityTypeBuilder(b.Metadata, b.ModelBuilder);
                    return entityTypeBuilder;
                });
            conventions.EntityTypeAddedConventions.Add(convention.Object);

            var nullConvention = new Mock<IEntityTypeConvention>();
            nullConvention.Setup(c => c.Apply(It.IsAny<InternalEntityTypeBuilder>())).Returns<InternalEntityTypeBuilder>(b =>
                {
                    Assert.Same(entityTypeBuilder, b);
                    return null;
                });
            conventions.EntityTypeAddedConventions.Add(nullConvention.Object);

            var extraConvention = new Mock<IEntityTypeConvention>();
            extraConvention.Setup(c => c.Apply(It.IsAny<InternalEntityTypeBuilder>())).Returns<InternalEntityTypeBuilder>(b =>
                {
                    Assert.False(true);
                    return null;
                });
            conventions.EntityTypeAddedConventions.Add(extraConvention.Object);

            var builder = new InternalModelBuilder(new Model(conventions));

            if (useBuilder)
            {
                Assert.Null(builder.Entity(typeof(Order), ConfigurationSource.Convention));
            }
            else
            {
                Assert.Null(builder.Metadata.AddEntityType(typeof(Order), ConfigurationSource.Convention));
            }

            Assert.NotNull(entityTypeBuilder);
        }
        /// <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 bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityType oldBaseType)
        {
            if (_sets != null)
            {
                var entityType = entityTypeBuilder.Metadata;

                if (oldBaseType == null
                    && entityType.BaseType != null)
                {
                    entityTypeBuilder.Relational(ConfigurationSource.Convention).ToTable(null);
                }
                else if (oldBaseType != null
                         && entityType.BaseType == null
                         && _sets.ContainsKey(entityType.ClrType))
                {
                    entityTypeBuilder.Relational(ConfigurationSource.Convention).ToTable(_sets[entityType.ClrType].Name);
                }
            }
            return true;
        }
        public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));

            var properties = entityTypeBuilder.Metadata.ClrType?.GetRuntimeProperties();
            if (properties == null)
            {
                return entityTypeBuilder;
            }

            foreach (var property in properties)
            {
                var attributes = property.GetCustomAttributes<NotMappedAttribute>(inherit: true);
                if (attributes.Any())
                {
                    entityTypeBuilder.Ignore(property.Name, ConfigurationSource.DataAnnotation);
                }
            }

            return entityTypeBuilder;
        }
        public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            var entityType = entityTypeBuilder.Metadata;
            var clrType = entityType.ClrType;
            if (clrType == null)
            {
                return entityTypeBuilder;
            }

            var directlyDerivedTypes = entityType.Model.GetEntityTypes().Where(t =>
                (t.BaseType == entityType.BaseType)
                && t.HasClrType()
                && (FindClosestBaseType(t) == entityType))
                .ToList();

            foreach (var directlyDerivedType in directlyDerivedTypes)
            {
                entityTypeBuilder.ModelBuilder.Entity(directlyDerivedType.ClrType, ConfigurationSource.Convention)
                    .HasBaseType(entityType, ConfigurationSource.Convention);
            }

            return entityTypeBuilder;
        }
 /// <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 bool ApplyIgnored(
     [NotNull] InternalEntityTypeBuilder entityTypeBuilder,
     [NotNull] PropertyInfo navigationPropertyInfo,
     [NotNull] Type targetClrType,
     [NotNull] TAttribute attribute) => throw new NotImplementedException();
Exemplo n.º 18
0
 private static void SetNavigationCandidates(
     InternalEntityTypeBuilder entityTypeBuilder,
     ImmutableSortedDictionary <PropertyInfo, Type> navigationCandidates)
 => entityTypeBuilder.HasAnnotation(NavigationCandidatesAnnotationName, navigationCandidates, ConfigurationSource.Convention);
Exemplo n.º 19
0
 private static void SetAmbigousNavigations(
     InternalEntityTypeBuilder entityTypeBuilder,
     ImmutableSortedDictionary <MemberInfo, Type> ambiguousNavigations)
 => entityTypeBuilder.HasAnnotation(AmbiguousNavigationsAnnotationName, ambiguousNavigations, ConfigurationSource.Convention);
 public RelationshipCandidate(
     InternalEntityTypeBuilder targetTypeBuilder,
     HashSet<PropertyInfo> navigations,
     HashSet<PropertyInfo> inverseNavigations)
 {
     TargetTypeBuilder = targetTypeBuilder;
     NavigationProperties = navigations;
     InverseProperties = inverseNavigations;
 }
            public InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
            {
                Applied = true;

                return(entityTypeBuilder);
            }
        public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            var entityType = entityTypeBuilder.Metadata;

            var navigationPairCandidates = new Dictionary<Type, Tuple<List<PropertyInfo>, List<PropertyInfo>>>();
            if (entityType.HasClrType)
            {
                foreach (var navigationPropertyInfo in entityType.ClrType.GetRuntimeProperties().OrderBy(p => p.Name))
                {
                    var entityClrType = navigationPropertyInfo.FindCandidateNavigationPropertyType();
                    if (entityClrType == null
                        || !entityTypeBuilder.CanAddNavigation(navigationPropertyInfo.Name, ConfigurationSource.Convention))
                    {
                        continue;
                    }

                    var targetEntityTypeBuilder = entityTypeBuilder.ModelBuilder.Entity(entityClrType, ConfigurationSource.Convention);
                    if (targetEntityTypeBuilder == null)
                    {
                        continue;
                    }

                    // The navigation could have been added when the target entity type was added
                    if (!entityTypeBuilder.CanAddNavigation(navigationPropertyInfo.Name, ConfigurationSource.Convention))
                    {
                        continue;
                    }

                    if (navigationPairCandidates.ContainsKey(targetEntityTypeBuilder.Metadata.ClrType))
                    {
                        if (entityType != targetEntityTypeBuilder.Metadata
                            || !navigationPairCandidates[targetEntityTypeBuilder.Metadata.ClrType].Item2.Contains(navigationPropertyInfo))
                        {
                            navigationPairCandidates[targetEntityTypeBuilder.Metadata.ClrType].Item1.Add(navigationPropertyInfo);
                        }
                        continue;
                    }

                    var navigations = new List<PropertyInfo> { navigationPropertyInfo };
                    var reverseNavigations = new List<PropertyInfo>();

                    navigationPairCandidates[targetEntityTypeBuilder.Metadata.ClrType] =
                        new Tuple<List<PropertyInfo>, List<PropertyInfo>>(navigations, reverseNavigations);
                    foreach (var reversePropertyInfo in targetEntityTypeBuilder.Metadata.ClrType.GetRuntimeProperties().OrderBy(p => p.Name))
                    {
                        var reverseEntityClrType = reversePropertyInfo.FindCandidateNavigationPropertyType();
                        if (reverseEntityClrType == null
                            || !targetEntityTypeBuilder.CanAddNavigation(reversePropertyInfo.Name, ConfigurationSource.Convention)
                            || entityType.ClrType != reverseEntityClrType
                            || navigationPropertyInfo == reversePropertyInfo)
                        {
                            continue;
                        }

                        reverseNavigations.Add(reversePropertyInfo);
                    }
                }

                foreach (var navigationPairCandidate in navigationPairCandidates)
                {
                    var navigationCandidates = navigationPairCandidate.Value.Item1;
                    var reverseNavigationCandidates = navigationPairCandidate.Value.Item2;

                    if (navigationCandidates.Count > 1
                        && reverseNavigationCandidates.Count > 0)
                    {
                        // Ambiguous navigations
                        return entityTypeBuilder;
                    }

                    if (reverseNavigationCandidates.Count > 1)
                    {
                        // Ambiguous navigations
                        return entityTypeBuilder;
                    }

                    foreach (var navigationCandidate in navigationCandidates)
                    {
                        var targetEntityTypeBuilder = entityTypeBuilder.ModelBuilder.Entity(navigationCandidate.FindCandidateNavigationPropertyType(), ConfigurationSource.Convention);
                        targetEntityTypeBuilder.Relationship(entityTypeBuilder, navigationCandidate, reverseNavigationCandidates.SingleOrDefault(), ConfigurationSource.Convention);
                    }
                }
            }

            // While running conventions on entityType, its source will be DataAnnotation or higher
            // Which means that entity won't be removed while being configured even if it is unreachable
            // This takes care of removing such unreachable entities (being run after we are done building relationships using this entity)
            entityTypeBuilder.ModelBuilder.RemoveEntityTypesUnreachableByNavigations(ConfigurationSource.DataAnnotation);
            return entityTypeBuilder;
        }
Exemplo n.º 23
0
 private static void SetDuplicateServiceProperties(
     InternalEntityTypeBuilder entityTypeBuilder,
     Dictionary <Type, HashSet <MemberInfo> > duplicateServiceProperties)
 => entityTypeBuilder.HasAnnotation(DuplicateServicePropertiesAnnotationName, duplicateServiceProperties, ConfigurationSource.Convention);
        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.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.
            if (Attribute.IsDefined(inverseNavigationPropertyInfo, typeof(InversePropertyAttribute)))
            {
                var inverseAttribute = inverseNavigationPropertyInfo.GetCustomAttribute <InversePropertyAttribute>(true);
                if (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);

            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.Navigations(
                            existingInverse.IsDependentToPrincipal() ? PropertyIdentity.None : (PropertyIdentity?)null,
                            existingInverse.IsDependentToPrincipal() ? (PropertyIdentity?)null : PropertyIdentity.None,
                            ConfigurationSource.DataAnnotation);
                    }
                }

                var existingNavigation = entityTypeBuilder.Metadata.FindNavigation(navigationMemberInfo);
                if (existingNavigation != null)
                {
                    var fk = existingNavigation.ForeignKey;
                    if (fk.IsOwnership ||
                        fk.DeclaringEntityType.Builder.RemoveForeignKey(fk, ConfigurationSource.DataAnnotation) == null)
                    {
                        fk.Builder.Navigations(
                            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.Navigations(
                            existingAmbiguousNavigation.IsDependentToPrincipal() ? PropertyIdentity.None : (PropertyIdentity?)null,
                            existingAmbiguousNavigation.IsDependentToPrincipal() ? (PropertyIdentity?)null : PropertyIdentity.None,
                            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 != null &&
                entityType.DefiningEntityType == targetEntityTypeBuilder.Metadata &&
                entityType.DefiningNavigationName != inverseNavigationPropertyInfo.Name)
            {
                _logger.NonDefiningInverseNavigationWarning(
                    entityType, navigationMemberInfo,
                    targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo,
                    entityType.DefiningEntityType.GetRuntimeProperties()[entityType.DefiningNavigationName]);
                return(null);
            }

            return(entityType.Model.ShouldBeOwnedType(entityType.ClrType) &&
                   !entityType.IsInOwnershipPath(targetEntityTypeBuilder.Metadata)
                ? targetEntityTypeBuilder.Owns(
                       entityTypeBuilder.Metadata.ClrType,
                       inverseNavigationPropertyInfo,
                       navigationMemberInfo,
                       ConfigurationSource.Convention)
                : targetEntityTypeBuilder.Relationship(
                       entityTypeBuilder,
                       inverseNavigationPropertyInfo,
                       navigationMemberInfo,
                       ConfigurationSource.DataAnnotation));
        }
Exemplo n.º 25
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 bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityType oldBaseType)
 => Apply(entityTypeBuilder) != null;
        public bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityType oldBaseType)
        {
            Apply(entityTypeBuilder);

            return(true);
        }
Exemplo n.º 27
0
 /// <inheritdoc />
 public void Apply(InternalEntityTypeBuilder entityTypeBuilder, Key key)
 {
     Apply(entityTypeBuilder);
 }
        /// <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 InternalPropertyBuilder Attach([NotNull] InternalEntityTypeBuilder entityTypeBuilder)
        {
            var newProperty = entityTypeBuilder.Metadata.FindProperty(Metadata.Name);
            InternalPropertyBuilder newPropertyBuilder;
            var configurationSource     = Metadata.GetConfigurationSource();
            var typeConfigurationSource = Metadata.GetTypeConfigurationSource();

            if (newProperty != null &&
                (newProperty.GetConfigurationSource().Overrides(configurationSource) ||
                 newProperty.GetTypeConfigurationSource().Overrides(typeConfigurationSource) ||
                 (Metadata.ClrType == newProperty.ClrType &&
                  Metadata.GetIdentifyingMemberInfo()?.Name == newProperty.GetIdentifyingMemberInfo()?.Name)))
            {
                newPropertyBuilder = newProperty.Builder;
                newProperty.UpdateConfigurationSource(configurationSource);
                if (typeConfigurationSource.HasValue)
                {
                    newProperty.UpdateTypeConfigurationSource(typeConfigurationSource.Value);
                }
            }
            else
            {
                newPropertyBuilder = Metadata.GetIdentifyingMemberInfo() == null
                    ? entityTypeBuilder.Property(Metadata.Name, Metadata.ClrType, configurationSource, Metadata.GetTypeConfigurationSource())
                    : entityTypeBuilder.Property(Metadata.GetIdentifyingMemberInfo(), configurationSource);
            }

            if (newProperty == Metadata)
            {
                return(newPropertyBuilder);
            }

            newPropertyBuilder.MergeAnnotationsFrom(Metadata);

            var oldBeforeSaveBehaviorConfigurationSource = Metadata.GetBeforeSaveBehaviorConfigurationSource();

            if (oldBeforeSaveBehaviorConfigurationSource.HasValue)
            {
                newPropertyBuilder.BeforeSave(
                    Metadata.GetBeforeSaveBehavior(),
                    oldBeforeSaveBehaviorConfigurationSource.Value);
            }

            var oldAfterSaveBehaviorConfigurationSource = Metadata.GetAfterSaveBehaviorConfigurationSource();

            if (oldAfterSaveBehaviorConfigurationSource.HasValue)
            {
                newPropertyBuilder.AfterSave(
                    Metadata.GetAfterSaveBehavior(),
                    oldAfterSaveBehaviorConfigurationSource.Value);
            }

            var oldIsNullableConfigurationSource = Metadata.GetIsNullableConfigurationSource();

            if (oldIsNullableConfigurationSource.HasValue)
            {
                newPropertyBuilder.IsRequired(!Metadata.IsNullable, oldIsNullableConfigurationSource.Value);
            }

            var oldIsConcurrencyTokenConfigurationSource = Metadata.GetIsConcurrencyTokenConfigurationSource();

            if (oldIsConcurrencyTokenConfigurationSource.HasValue)
            {
                newPropertyBuilder.IsConcurrencyToken(
                    Metadata.IsConcurrencyToken,
                    oldIsConcurrencyTokenConfigurationSource.Value);
            }

            var oldValueGeneratedConfigurationSource = Metadata.GetValueGeneratedConfigurationSource();

            if (oldValueGeneratedConfigurationSource.HasValue)
            {
                newPropertyBuilder.ValueGenerated(Metadata.ValueGenerated, oldValueGeneratedConfigurationSource.Value);
            }

            var oldFieldInfoConfigurationSource = Metadata.GetFieldInfoConfigurationSource();

            if (oldFieldInfoConfigurationSource.HasValue)
            {
                newPropertyBuilder.HasFieldInfo(Metadata.FieldInfo, oldFieldInfoConfigurationSource.Value);
            }

            return(newPropertyBuilder);
        }
Exemplo n.º 29
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 InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
 => !entityTypeBuilder.Metadata.HasClrType() ? entityTypeBuilder : DiscoverRelationships(entityTypeBuilder);
Exemplo n.º 30
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 InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            var entityType = entityTypeBuilder.Metadata;

            if (!entityType.HasClrType())
            {
                return(entityTypeBuilder);
            }

            var candidates = entityType.GetRuntimeProperties().Values;

            foreach (var propertyInfo in candidates)
            {
                if (entityTypeBuilder.IsIgnored(propertyInfo.GetSimpleMemberName(), ConfigurationSource.Convention) ||
                    entityType.FindProperty(propertyInfo) != null ||
                    entityType.FindNavigation(propertyInfo) != null ||
                    !propertyInfo.IsCandidateProperty(publicOnly: false) ||
                    (propertyInfo.IsCandidateProperty() &&
                     _typeMappingSource.FindMapping(propertyInfo) != null))
                {
                    continue;
                }

                var factory = _parameterBindingFactories.FindFactory(propertyInfo.PropertyType, propertyInfo.GetSimpleMemberName());
                if (factory == null)
                {
                    continue;
                }

                var duplicateMap = GetDuplicateServiceProperties(entityType);
                if (duplicateMap != null &&
                    duplicateMap.TryGetValue(propertyInfo.PropertyType, out var duplicateServiceProperties))
                {
                    duplicateServiceProperties.Add(propertyInfo);

                    return(entityTypeBuilder);
                }

                var otherServicePropertySameType = entityType.GetServiceProperties()
                                                   .FirstOrDefault(p => p.ClrType == propertyInfo.PropertyType);
                if (otherServicePropertySameType != null)
                {
                    if (ConfigurationSource.Convention.Overrides(otherServicePropertySameType.GetConfigurationSource()))
                    {
                        otherServicePropertySameType.DeclaringEntityType.RemoveServiceProperty(otherServicePropertySameType.Name);
                    }

                    AddDuplicateServiceProperty(entityTypeBuilder, propertyInfo);
                    AddDuplicateServiceProperty(entityTypeBuilder, otherServicePropertySameType.GetIdentifyingMemberInfo());

                    return(entityTypeBuilder);
                }

                entityTypeBuilder.ServiceProperty(propertyInfo, ConfigurationSource.Convention)?.SetParameterBinding(
                    (ServiceParameterBinding)factory.Bind(entityType, propertyInfo.PropertyType, propertyInfo.GetSimpleMemberName()),
                    ConfigurationSource.Convention);
            }

            return(entityTypeBuilder);
        }
Exemplo n.º 31
0
        private 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 &&
                     (!targetEntityType.Model.ShouldBeOwnedType(targetEntityType.ClrType) ||
                      entityType.IsInOwnershipPath(targetEntityType))) ||
                    relationshipCandidate.InverseProperties.Count > 1 ||
                    isAmbiguousOnBase ||
                    HasDeclaredAmbiguousNavigationsTo(entityType, targetEntityType.ClrType) ||
                    HasDeclaredAmbiguousNavigationsTo(targetEntityType, entityType.ClrType))
                {
                    if (!isAmbiguousOnBase)
                    {
                        AddAmbiguous(entityTypeBuilder, relationshipCandidate.NavigationProperties, targetEntityType.ClrType);

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

                        _logger.MultipleNavigationProperties(
                            relationshipCandidate.NavigationProperties.Count == 0
                                ? new[] { new Tuple <MemberInfo, Type>(null, targetEntityType.ClrType) }
                                : relationshipCandidate.NavigationProperties.Select(n => new Tuple <MemberInfo, Type>(n, entityType.ClrType)),
                            relationshipCandidate.InverseProperties.Count == 0
                                ? new[] { new Tuple <MemberInfo, Type>(null, targetEntityType.ClrType) }
                                : relationshipCandidate.InverseProperties.Select(n => new Tuple <MemberInfo, Type>(n, targetEntityType.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 &&
                        !targetEntityType.Model.ShouldBeOwnedType(targetEntityType.ClrType))
                    {
                        continue;
                    }

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

                    var inverse = relationshipCandidate.InverseProperties.SingleOrDefault();
                    if (inverse == null)
                    {
                        if (targetEntityType.Model.ShouldBeOwnedType(targetEntityType.ClrType) &&
                            !entityType.IsInOwnershipPath(targetEntityType))
                        {
                            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.Model.ShouldBeOwnedType(targetEntityType.ClrType) &&
                            !entityType.IsInOwnershipPath(targetEntityType))
                        {
                            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);
                }
            }
        }
 public static FbEntityTypeBuilderAnnotations Firebird(this InternalEntityTypeBuilder builder, ConfigurationSource configurationSource)
 => new FbEntityTypeBuilderAnnotations(builder, configurationSource);
Exemplo n.º 33
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(entityType, navigationPropertyInfo, referencingNavigationsWithAttribute))
            {
                var existingInverse = targetEntityTypeBuilder.Metadata.FindNavigation(inverseNavigationPropertyInfo)?.FindInverse();
                if (existingInverse != null &&
                    IsAmbiguousInverse(existingInverse.DeclaringEntityType, existingInverse.PropertyInfo, 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 static void RunConvention(InternalEntityTypeBuilder entityBuilder)
 => new ValueGenerationConvention(CreateDependencies())
 .ProcessEntityTypePrimaryKeyChanged(
     entityBuilder, entityBuilder.Metadata.FindPrimaryKey(), null,
     new ConventionContext <IConventionKey>(entityBuilder.Metadata.Model.ConventionDispatcher));
Exemplo n.º 35
0
 private void SetIdentity(InternalEntityTypeBuilder entityTypeBuilder, Property property)
     => entityTypeBuilder.Property(
         property.Name,
         ((IProperty)property).ClrType,
         ConfigurationSource.Convention)
         ?.ValueGenerated(ValueGenerated.OnAdd, ConfigurationSource.Convention);
 private static void RunConvention(InternalEntityTypeBuilder entityBuilder, ForeignKey foreignKey)
 => new ValueGenerationConvention(CreateDependencies())
 .ProcessForeignKeyRemoved(
     entityBuilder, foreignKey,
     new ConventionContext <IConventionForeignKey>(entityBuilder.Metadata.Model.ConventionDispatcher));
 public virtual bool Apply(InternalEntityTypeBuilder entityTypeBuilder, string ignoredMemberName)
     => Apply(entityTypeBuilder) != null;
Exemplo n.º 38
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 RelationalEntityTypeBuilderAnnotations(
     [NotNull] InternalEntityTypeBuilder internalBuilder,
     ConfigurationSource configurationSource)
     : base(new RelationalAnnotationsBuilder(internalBuilder, configurationSource))
 {
 }
        private IReadOnlyList<RelationshipCandidate> RemoveIncompatibleWithExistingRelationships(
            IReadOnlyList<RelationshipCandidate> relationshipCandidates,
            InternalEntityTypeBuilder entityTypeBuilder)
        {
            var filteredRelationshipCandidates = new List<RelationshipCandidate>();
            foreach (var relationshipCandidate in relationshipCandidates)
            {
                var targetEntityTypeBuilder = relationshipCandidate.TargetTypeBuilder;
                var revisitNavigations = true;
                while (revisitNavigations)
                {
                    revisitNavigations = false;
                    foreach (var navigationProperty in relationshipCandidate.NavigationProperties)
                    {
                        var existingNavigation = entityTypeBuilder.Metadata.FindNavigation(navigationProperty.Name);
                        if (existingNavigation != null
                            && (existingNavigation.DeclaringEntityType != entityTypeBuilder.Metadata
                                || existingNavigation.GetTargetType() != targetEntityTypeBuilder.Metadata))
                        {
                            relationshipCandidate.NavigationProperties.Remove(navigationProperty);
                            revisitNavigations = true;
                            break;
                        }

                        var compatibleInverseProperties = new List<PropertyInfo>();
                        Navigation existingInverse = null;
                        foreach (var inversePropertyInfo in relationshipCandidate.InverseProperties)
                        {
                            if ((existingNavigation != null
                                 && !CanMergeWith(existingNavigation, inversePropertyInfo.Name, targetEntityTypeBuilder)))
                            {
                                continue;
                            }

                            existingInverse = targetEntityTypeBuilder.Metadata.FindNavigation(inversePropertyInfo.Name);
                            if (existingInverse != null)
                            {
                                if (existingInverse.DeclaringEntityType != targetEntityTypeBuilder.Metadata
                                    || !CanMergeWith(existingInverse, navigationProperty.Name, entityTypeBuilder))
                                {
                                    continue;
                                }

                                var otherEntityType = existingInverse.ForeignKey.ResolveOtherEntityType(
                                    existingInverse.DeclaringEntityType);
                                if (!entityTypeBuilder.Metadata.ClrType.GetTypeInfo()
                                    .IsAssignableFrom(otherEntityType.ClrType.GetTypeInfo()))
                                {
                                    continue;
                                }
                            }

                            compatibleInverseProperties.Add(inversePropertyInfo);
                        }

                        if (compatibleInverseProperties.Count == 0)
                        {
                            relationshipCandidate.NavigationProperties.Remove(navigationProperty);
                            revisitNavigations = true;
                            filteredRelationshipCandidates.Add(new RelationshipCandidate(
                                targetEntityTypeBuilder,
                                new HashSet<PropertyInfo> { navigationProperty },
                                new HashSet<PropertyInfo>()));
                            if (relationshipCandidate.TargetTypeBuilder.Metadata == entityTypeBuilder.Metadata
                                && relationshipCandidate.InverseProperties.Count > 0)
                            {
                                var nextSelfRefCandidate = relationshipCandidate.InverseProperties.First();
                                relationshipCandidate.NavigationProperties.Add(nextSelfRefCandidate);
                                relationshipCandidate.InverseProperties.Remove(nextSelfRefCandidate);
                            }
                            break;
                        }

                        if (compatibleInverseProperties.Count == 1
                            && (relationshipCandidate.NavigationProperties.Count == 1
                                || (existingInverse != null
                                    && !CanMergeWith(existingInverse, null, entityTypeBuilder))))
                        {
                            var inverseProperty = compatibleInverseProperties[0];
                            relationshipCandidate.NavigationProperties.Remove(navigationProperty);
                            relationshipCandidate.InverseProperties.Remove(inverseProperty);
                            revisitNavigations = true;
                            filteredRelationshipCandidates.Add(new RelationshipCandidate(
                                targetEntityTypeBuilder,
                                new HashSet<PropertyInfo> { navigationProperty },
                                new HashSet<PropertyInfo> { inverseProperty }));
                            if (relationshipCandidate.TargetTypeBuilder.Metadata == entityTypeBuilder.Metadata
                                && relationshipCandidate.InverseProperties.Count > 0)
                            {
                                var nextSelfRefCandidate = relationshipCandidate.InverseProperties.First();
                                relationshipCandidate.NavigationProperties.Add(nextSelfRefCandidate);
                                relationshipCandidate.InverseProperties.Remove(nextSelfRefCandidate);
                            }
                            break;
                        }
                    }
                }

                if (relationshipCandidate.NavigationProperties.Count > 0)
                {
                    filteredRelationshipCandidates.Add(relationshipCandidate);
                }
            }

            return filteredRelationshipCandidates;
        }
 /// <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 bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityType oldBaseType)
     => Apply(entityTypeBuilder) != null;
Exemplo n.º 41
0
 public virtual void Apply(InternalEntityTypeBuilder entityTypeBuilder, ForeignKey foreignKey)
 {
     var properties = foreignKey.Properties;
     SetValueGeneration(properties.Where(property => property.IsKey()));
     SetIdentity(properties, entityTypeBuilder.Metadata);
 }
Exemplo n.º 42
0
            public InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
            {
                Applied = true;

                return entityTypeBuilder;
            }
Exemplo n.º 43
0
 /// <summary>
 ///     <para>
 ///         Initializes a new instance of the <see cref="EntityTypeBuilder{TEntity}" /> class to configure a
 ///         given entity type.
 ///     </para>
 ///     <para>
 ///         Instances of this class are returned from methods when using the <see cref="ModelBuilder" /> API
 ///         and it is not designed to be directly constructed in your application code.
 ///     </para>
 /// </summary>
 /// <param name="builder"> Internal typeBuilder for the entity type being configured. </param>
 public EntityTypeBuilder([NotNull] InternalEntityTypeBuilder builder)
     : base(builder)
 {
 }
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual InternalSkipNavigationBuilder Attach(
            [CanBeNull] InternalEntityTypeBuilder entityTypeBuilder = null,
            [CanBeNull] EntityType targetEntityType = null,
            [CanBeNull] InternalSkipNavigationBuilder inverseBuilder = null)
        {
            entityTypeBuilder ??= Metadata.DeclaringEntityType.Builder;
            if (entityTypeBuilder == null)
            {
                entityTypeBuilder = Metadata.DeclaringEntityType.Model.FindEntityType(Metadata.DeclaringEntityType.Name)?.Builder;
                if (entityTypeBuilder == null)
                {
                    return(null);
                }
            }

            targetEntityType ??= Metadata.TargetEntityType;
            if (targetEntityType.Builder == null)
            {
                targetEntityType = Metadata.DeclaringEntityType.Model.FindEntityType(targetEntityType.Name);
                if (targetEntityType == null)
                {
                    return(null);
                }
            }

            var newSkipNavigationBuilder = entityTypeBuilder.HasSkipNavigation(
                Metadata.CreateMemberIdentity(),
                targetEntityType,
                Metadata.GetConfigurationSource(),
                Metadata.IsCollection,
                Metadata.IsOnDependent);

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

            newSkipNavigationBuilder.MergeAnnotationsFrom(Metadata);

            var foreignKeyConfigurationSource = Metadata.GetForeignKeyConfigurationSource();

            if (foreignKeyConfigurationSource.HasValue)
            {
                var foreignKey = Metadata.ForeignKey;
                if (foreignKey.Builder == null)
                {
                    foreignKey = InternalForeignKeyBuilder.FindCurrentForeignKeyBuilder(
                        foreignKey.PrincipalEntityType,
                        foreignKey.DeclaringEntityType,
                        foreignKey.DependentToPrincipal?.CreateMemberIdentity(),
                        foreignKey.PrincipalToDependent?.CreateMemberIdentity(),
                        dependentProperties: foreignKey.Properties,
                        principalProperties: foreignKey.PrincipalKey.Properties)?.Metadata;
                }

                if (foreignKey != null)
                {
                    newSkipNavigationBuilder.HasForeignKey(foreignKey, foreignKeyConfigurationSource.Value);
                }
            }

            var inverseConfigurationSource = Metadata.GetInverseConfigurationSource();

            if (inverseConfigurationSource.HasValue)
            {
                var inverse = Metadata.Inverse;
                if (inverse.Builder == null)
                {
                    inverse = inverse.DeclaringEntityType.FindSkipNavigation(inverse.Name);
                }

                if (inverseBuilder != null)
                {
                    inverse = inverseBuilder.Attach(targetEntityType.Builder, entityTypeBuilder.Metadata)?.Metadata
                              ?? inverse;
                }

                if (inverse != null)
                {
                    newSkipNavigationBuilder.HasInverse(inverse, inverseConfigurationSource.Value);
                }
            }

            var propertyAccessModeConfigurationSource = Metadata.GetPropertyAccessModeConfigurationSource();

            if (propertyAccessModeConfigurationSource.HasValue)
            {
                newSkipNavigationBuilder.UsePropertyAccessMode(
                    ((ISkipNavigation)Metadata).GetPropertyAccessMode(), propertyAccessModeConfigurationSource.Value);
            }

            var oldFieldInfoConfigurationSource = Metadata.GetFieldInfoConfigurationSource();

            if (oldFieldInfoConfigurationSource.HasValue &&
                newSkipNavigationBuilder.CanSetField(Metadata.FieldInfo, oldFieldInfoConfigurationSource))
            {
                newSkipNavigationBuilder.HasField(Metadata.FieldInfo, oldFieldInfoConfigurationSource.Value);
            }

            return(newSkipNavigationBuilder);
        }
Exemplo n.º 45
0
        private IReadOnlyList <RelationshipCandidate> FindRelationshipCandidates(InternalEntityTypeBuilder entityTypeBuilder)
        {
            var relationshipCandidates = new Dictionary <EntityType, RelationshipCandidate>();
            var ownership = entityTypeBuilder.Metadata.FindOwnership();

            if (ownership == null &&
                entityTypeBuilder.Metadata.Model.ShouldBeOwnedType(entityTypeBuilder.Metadata.ClrType))
            {
                return(relationshipCandidates.Values.ToList());
            }

            var navigationCandidates = GetNavigationCandidates(entityTypeBuilder.Metadata);

            foreach (var candidateTuple in navigationCandidates)
            {
                var navigationPropertyInfo = candidateTuple.Key;
                var targetClrType          = candidateTuple.Value;

                if (!IsCandidateNavigationProperty(entityTypeBuilder, navigationPropertyInfo.Name, navigationPropertyInfo))
                {
                    continue;
                }

                InternalEntityTypeBuilder candidateTargetEntityTypeBuilder = null;
                if (!entityTypeBuilder.ModelBuilder.Metadata.HasEntityTypeWithDefiningNavigation(targetClrType))
                {
                    candidateTargetEntityTypeBuilder = entityTypeBuilder.ModelBuilder.Entity(targetClrType, ConfigurationSource.Convention);
                }
                else if (!targetClrType.GetTypeInfo().Equals(entityTypeBuilder.Metadata.ClrType.GetTypeInfo()) &&
                         !entityTypeBuilder.Metadata.IsInDefinitionPath(targetClrType))
                {
                    candidateTargetEntityTypeBuilder =
                        entityTypeBuilder.Metadata.FindNavigation(navigationPropertyInfo.Name)?.GetTargetType().Builder
                        ?? entityTypeBuilder.ModelBuilder.Metadata.FindEntityType(
                            targetClrType, navigationPropertyInfo.Name, entityTypeBuilder.Metadata)?.Builder
                        ?? entityTypeBuilder.ModelBuilder.Entity(
                            targetClrType, navigationPropertyInfo.Name, entityTypeBuilder.Metadata, ConfigurationSource.Convention);
                }

                if (candidateTargetEntityTypeBuilder == null ||
                    (entityTypeBuilder.ModelBuilder.Metadata.ShouldBeOwnedType(entityTypeBuilder.Metadata.ClrType) &&
                     candidateTargetEntityTypeBuilder.Metadata == entityTypeBuilder.Metadata))
                {
                    continue;
                }

                var candidateTargetEntityType = candidateTargetEntityTypeBuilder.Metadata;
                if (candidateTargetEntityType.IsQueryType)
                {
                    continue;
                }

                if (!entityTypeBuilder.Metadata.Model.ShouldBeOwnedType(candidateTargetEntityType.ClrType))
                {
                    var targetOwnership = candidateTargetEntityType.FindOwnership();
                    if (targetOwnership != null &&
                        (targetOwnership.PrincipalEntityType != entityTypeBuilder.Metadata ||
                         targetOwnership.PrincipalToDependent.Name != navigationPropertyInfo.Name))
                    {
                        if (ownership == null ||
                            ownership.PrincipalEntityType != candidateTargetEntityType)
                        {
                            continue;
                        }
                    }
                }
                else if ( // #8172
                    //ownership != null &&
                    navigationPropertyInfo.PropertyType.TryGetSequenceType() != null)
                {
                    continue;
                }

                var entityType = entityTypeBuilder.Metadata;

                if (relationshipCandidates.TryGetValue(candidateTargetEntityType, out var existingCandidate))
                {
                    if (candidateTargetEntityType != entityType ||
                        !existingCandidate.InverseProperties.Contains(navigationPropertyInfo))
                    {
                        if (!existingCandidate.NavigationProperties.Contains(navigationPropertyInfo))
                        {
                            existingCandidate.NavigationProperties.Add(navigationPropertyInfo);
                        }
                    }

                    continue;
                }

                var navigations = new List <PropertyInfo>
                {
                    navigationPropertyInfo
                };
                var inverseCandidates           = GetNavigationCandidates(candidateTargetEntityType);
                var inverseNavigationCandidates = new List <PropertyInfo>();

                foreach (var inverseCandidateTuple in inverseCandidates)
                {
                    var inversePropertyInfo = inverseCandidateTuple.Key;
                    var inverseTargetType   = inverseCandidateTuple.Value;

                    if (inverseTargetType != entityType.ClrType ||
                        navigationPropertyInfo.IsSameAs(inversePropertyInfo) ||
                        entityType.IsQueryType ||
                        (ownership != null &&
                         (ownership.PrincipalEntityType != candidateTargetEntityType ||
                          ownership.PrincipalToDependent.Name != inversePropertyInfo.Name)) ||
                        (entityType.HasDefiningNavigation() &&
                         (entityType.DefiningEntityType != candidateTargetEntityType ||
                          entityType.DefiningNavigationName != inversePropertyInfo.Name)) ||
                        !IsCandidateNavigationProperty(
                            candidateTargetEntityTypeBuilder, inversePropertyInfo.Name, inversePropertyInfo))
                    {
                        continue;
                    }

                    if (!inverseNavigationCandidates.Contains(inversePropertyInfo))
                    {
                        inverseNavigationCandidates.Add(inversePropertyInfo);
                    }
                }

                relationshipCandidates[candidateTargetEntityType] =
                    new RelationshipCandidate(candidateTargetEntityTypeBuilder, navigations, inverseNavigationCandidates);
            }

            return(relationshipCandidates.Values.ToList());
        }
Exemplo n.º 46
0
 protected override EntityTypeBuilder New(InternalEntityTypeBuilder builder)
 => new EntityTypeBuilder <TEntity>(builder);
Exemplo n.º 47
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 InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));

            var entityType = entityTypeBuilder.Metadata;

            if (entityType.BaseType != null ||
                entityType.IsQueryType ||
                !ConfigurationSource.Convention.Overrides(entityType.GetPrimaryKeyConfigurationSource()))
            {
                return(entityTypeBuilder);
            }

            List <Property> keyProperties = null;
            var             definingFk    = entityType.FindDefiningNavigation()?.ForeignKey
                                            ?? entityType.FindOwnership();

            if (definingFk != null &&
                definingFk.DeclaringEntityType != entityType)
            {
                definingFk = null;
            }

            if (definingFk?.IsUnique == true)
            {
                keyProperties = definingFk.Properties.ToList();
            }

            if (keyProperties == null)
            {
                var candidateProperties = entityType.GetProperties().Where(
                    p => !p.IsShadowProperty ||
                    !ConfigurationSource.Convention.Overrides(p.GetConfigurationSource())).ToList();
                keyProperties = (List <Property>)DiscoverKeyProperties(entityType, candidateProperties);
                if (keyProperties.Count > 1)
                {
                    Logger?.MultiplePrimaryKeyCandidates(keyProperties[0], keyProperties[1]);
                    return(entityTypeBuilder);
                }
            }

            if (definingFk?.IsUnique == false)
            {
                if (keyProperties.Count == 0 ||
                    definingFk.Properties.Contains(keyProperties.First()))
                {
                    var shadowProperty = entityType.FindPrimaryKey()?.Properties.Last();
                    if (shadowProperty == null ||
                        entityType.FindPrimaryKey().Properties.Count == 1 ||
                        definingFk.Properties.Contains(shadowProperty))
                    {
                        shadowProperty = entityTypeBuilder.CreateUniqueProperty("Id", typeof(int), isRequired: true);
                    }

                    keyProperties.Clear();
                    keyProperties.Add(shadowProperty);
                }

                var extraProperty = keyProperties[0];
                keyProperties.RemoveAt(0);
                keyProperties.AddRange(definingFk.Properties);
                keyProperties.Add(extraProperty);
            }

            if (keyProperties.Count > 0)
            {
                entityTypeBuilder.PrimaryKey(keyProperties, ConfigurationSource.Convention);
            }

            return(entityTypeBuilder);
        }
 private static void VerifyOneToManyDependent(InternalEntityTypeBuilder entityTypeBuilder, bool unidirectional, bool dependentHasPK = true)
 {
     VerifyOneToMany(entityTypeBuilder.Metadata.Model, dependentHasPK, hasNavigationToDependent: !unidirectional, hasNavigationToPrincipal: true);
 }
        public void Can_ignore_property_that_is_part_of_lower_source_index()
        {
            var modelBuilder = CreateModelBuilder();
            var entityType = modelBuilder.Metadata.AddEntityType(typeof(Order));
            var entityBuilder = new InternalEntityTypeBuilder(entityType, modelBuilder);

            Assert.NotNull(entityBuilder.Index(new[] { Order.IdProperty, Order.CustomerIdProperty }, ConfigurationSource.DataAnnotation));

            Assert.True(entityBuilder.Ignore(Order.CustomerIdProperty.Name, ConfigurationSource.Explicit));

            Assert.Empty(entityBuilder.Metadata.Properties.Where(p => p.Name == Order.CustomerIdProperty.Name));
            Assert.Empty(entityBuilder.Metadata.Indexes);
        }
Exemplo n.º 50
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 bool Apply(InternalEntityTypeBuilder entityTypeBuilder, string ignoredMemberName)
 {
     Apply(entityTypeBuilder.Metadata);
     return(true);
 }
Exemplo n.º 51
0
        private static IReadOnlyList <RelationshipCandidate> RemoveIncompatibleWithExistingRelationships(
            IReadOnlyList <RelationshipCandidate> relationshipCandidates,
            InternalEntityTypeBuilder entityTypeBuilder)
        {
            if (relationshipCandidates.Count == 0)
            {
                return(relationshipCandidates);
            }

            var filteredRelationshipCandidates = new List <RelationshipCandidate>();

            foreach (var relationshipCandidate in relationshipCandidates)
            {
                var targetEntityTypeBuilder = relationshipCandidate.TargetTypeBuilder;
                while (relationshipCandidate.NavigationProperties.Count > 0)
                {
                    var navigationProperty = relationshipCandidate.NavigationProperties[0];
                    var existingNavigation = entityTypeBuilder.Metadata.FindNavigation(navigationProperty.Name);
                    if (existingNavigation != null &&
                        (existingNavigation.DeclaringEntityType != entityTypeBuilder.Metadata ||
                         existingNavigation.GetTargetType() != targetEntityTypeBuilder.Metadata))
                    {
                        relationshipCandidate.NavigationProperties.Remove(navigationProperty);
                        continue;
                    }

                    if (relationshipCandidate.NavigationProperties.Count == 1 &&
                        relationshipCandidate.InverseProperties.Count == 0)
                    {
                        break;
                    }

                    PropertyInfo compatibleInverse = null;
                    foreach (var inverseProperty in relationshipCandidate.InverseProperties)
                    {
                        if (IsCompatibleInverse(
                                navigationProperty, inverseProperty, entityTypeBuilder, targetEntityTypeBuilder))
                        {
                            if (compatibleInverse == null)
                            {
                                compatibleInverse = inverseProperty;
                            }
                            else
                            {
                                goto NextCandidate;
                            }
                        }
                    }

                    if (compatibleInverse == null)
                    {
                        relationshipCandidate.NavigationProperties.Remove(navigationProperty);

                        filteredRelationshipCandidates.Add(
                            new RelationshipCandidate(
                                targetEntityTypeBuilder,
                                new List <PropertyInfo>
                        {
                            navigationProperty
                        },
                                new List <PropertyInfo>()));

                        if (relationshipCandidate.TargetTypeBuilder.Metadata == entityTypeBuilder.Metadata &&
                            relationshipCandidate.InverseProperties.Count > 0)
                        {
                            var nextSelfRefCandidate = relationshipCandidate.InverseProperties.First();
                            if (!relationshipCandidate.NavigationProperties.Contains(nextSelfRefCandidate))
                            {
                                relationshipCandidate.NavigationProperties.Add(nextSelfRefCandidate);
                            }

                            relationshipCandidate.InverseProperties.Remove(nextSelfRefCandidate);
                        }

                        continue;
                    }

                    var noOtherCompatibleNavigation = true;
                    foreach (var n in relationshipCandidate.NavigationProperties)
                    {
                        if (n != navigationProperty &&
                            IsCompatibleInverse(n, compatibleInverse, entityTypeBuilder, targetEntityTypeBuilder))
                        {
                            noOtherCompatibleNavigation = false;
                            break;
                        }
                    }

                    if (noOtherCompatibleNavigation)
                    {
                        relationshipCandidate.NavigationProperties.Remove(navigationProperty);
                        relationshipCandidate.InverseProperties.Remove(compatibleInverse);

                        filteredRelationshipCandidates.Add(
                            new RelationshipCandidate(
                                targetEntityTypeBuilder,
                                new List <PropertyInfo>
                        {
                            navigationProperty
                        },
                                new List <PropertyInfo>
                        {
                            compatibleInverse
                        })
                            );

                        if (relationshipCandidate.TargetTypeBuilder.Metadata == entityTypeBuilder.Metadata &&
                            relationshipCandidate.NavigationProperties.Count == 0 &&
                            relationshipCandidate.InverseProperties.Count > 0)
                        {
                            var nextSelfRefCandidate = relationshipCandidate.InverseProperties.First();
                            if (!relationshipCandidate.NavigationProperties.Contains(nextSelfRefCandidate))
                            {
                                relationshipCandidate.NavigationProperties.Add(nextSelfRefCandidate);
                            }

                            relationshipCandidate.InverseProperties.Remove(nextSelfRefCandidate);
                        }

                        continue;
                    }

NextCandidate:
                    break;
                }

                if (relationshipCandidate.NavigationProperties.Count > 0 ||
                    relationshipCandidate.InverseProperties.Count > 0)
                {
                    filteredRelationshipCandidates.Add(relationshipCandidate);
                }
                else if (relationshipCandidate.TargetTypeBuilder.Metadata.HasDefiningNavigation() &&
                         filteredRelationshipCandidates.All(
                             c => c.TargetTypeBuilder.Metadata != relationshipCandidate.TargetTypeBuilder.Metadata))
                {
                    entityTypeBuilder.ModelBuilder
                    .RemoveEntityType(relationshipCandidate.TargetTypeBuilder.Metadata, ConfigurationSource.Convention);
                }
            }

            return(filteredRelationshipCandidates);
        }
        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);
                }
            }
        }
Exemplo n.º 53
0
        private void SetIdentity(InternalEntityTypeBuilder entityTypeBuilder, Property property)
        {
            var propertyBuilder = entityTypeBuilder.Property(
                property.Name,
                ((IProperty)property).ClrType,
                ConfigurationSource.Convention);

            propertyBuilder?.ValueGenerated(ValueGenerated.OnAdd, ConfigurationSource.Convention);
            propertyBuilder?.UseValueGenerator(true, ConfigurationSource.Convention);
        }
        public virtual bool Apply(InternalEntityTypeBuilder entityTypeBuilder, EntityType oldBaseType)
        {
            if (oldBaseType != null)
            {
                var oldBaseTypeBuilder = entityTypeBuilder.ModelBuilder.Entity(oldBaseType.Name, ConfigurationSource.Convention);
                if (oldBaseTypeBuilder != null)
                {
                    ApplyOnRelatedEntityTypes(entityTypeBuilder.ModelBuilder, oldBaseTypeBuilder.Metadata);
                    Apply(oldBaseTypeBuilder);
                }
            }

            ApplyOnRelatedEntityTypes(entityTypeBuilder.ModelBuilder, entityTypeBuilder.Metadata);
            return Apply(entityTypeBuilder) != null;
        }
        public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            var entityType = entityTypeBuilder.Metadata;

            var navigationPairCandidates = new Dictionary<InternalEntityTypeBuilder, Tuple<List<PropertyInfo>, List<PropertyInfo>>>();
            if (entityType.HasClrType)
            {
                foreach (var navigationPropertyInfo in entityType.ClrType.GetRuntimeProperties().OrderBy(p => p.Name))
                {
                    Type entityClrType;
                    if (!navigationPropertyInfo.IsCandidateNavigationProperty(out entityClrType)
                        || !entityTypeBuilder.CanAddNavigation(navigationPropertyInfo.Name, ConfigurationSource.Convention))
                    {
                        continue;
                    }

                    var targetEntityTypeBuilder = entityTypeBuilder.ModelBuilder.Entity(entityClrType, ConfigurationSource.Convention);
                    if (targetEntityTypeBuilder == null)
                    {
                        continue;
                    }

                    // The navigation could have been added when the target entity type was added
                    if (!entityTypeBuilder.CanAddNavigation(navigationPropertyInfo.Name, ConfigurationSource.Convention))
                    {
                        continue;
                    }

                    if (navigationPairCandidates.ContainsKey(targetEntityTypeBuilder))
                    {
                        if (entityType != targetEntityTypeBuilder.Metadata
                            || !navigationPairCandidates[targetEntityTypeBuilder].Item2.Contains(navigationPropertyInfo))
                        {
                            navigationPairCandidates[targetEntityTypeBuilder].Item1.Add(navigationPropertyInfo);
                        }
                        continue;
                    }

                    var navigations = new List<PropertyInfo> { navigationPropertyInfo };
                    var reverseNavigations = new List<PropertyInfo>();

                    navigationPairCandidates[targetEntityTypeBuilder] =
                        new Tuple<List<PropertyInfo>, List<PropertyInfo>>(navigations, reverseNavigations);
                    foreach (var reversePropertyInfo in targetEntityTypeBuilder.Metadata.ClrType.GetRuntimeProperties().OrderBy(p => p.Name))
                    {
                        Type reverseEntityClrType;
                        if (!reversePropertyInfo.IsCandidateNavigationProperty(out reverseEntityClrType)
                            || !targetEntityTypeBuilder.CanAddNavigation(reversePropertyInfo.Name, ConfigurationSource.Convention)
                            || entityType.ClrType != reverseEntityClrType
                            || navigationPropertyInfo == reversePropertyInfo)
                        {
                            continue;
                        }

                        reverseNavigations.Add(reversePropertyInfo);
                    }
                }

                foreach (var navigationPairCandidate in navigationPairCandidates)
                {
                    var targetEntityTypeBuilder = navigationPairCandidate.Key;
                    var navigationCandidates = navigationPairCandidate.Value.Item1;
                    var reverseNavigationCandidates = navigationPairCandidate.Value.Item2;

                    if (navigationCandidates.Count > 1
                        && reverseNavigationCandidates.Count > 0)
                    {
                        // Ambiguous navigations
                        return entityTypeBuilder;
                    }

                    if (reverseNavigationCandidates.Count > 1)
                    {
                        // Ambiguous navigations
                        return entityTypeBuilder;
                    }

                    foreach (var navigationCandidate in navigationCandidates)
                    {
                        TryBuildRelationship(entityTypeBuilder, targetEntityTypeBuilder, navigationCandidate, reverseNavigationCandidates.SingleOrDefault());
                    }
                }
            }

            return entityTypeBuilder;
        }
Exemplo n.º 56
0
        private InternalRelationshipBuilder ReuniquifyTemporaryProperties(ForeignKey foreignKey, bool force)
        {
            if (!force &&
                (foreignKey.GetPropertiesConfigurationSource() != null ||
                 !foreignKey.DeclaringEntityType.Builder.ShouldReuniquifyTemporaryProperties(
                     foreignKey.Properties,
                     foreignKey.PrincipalKey.Properties,
                     foreignKey.IsRequired && foreignKey.GetIsRequiredConfigurationSource().Overrides(ConfigurationSource.Convention),
                     GetPropertyBaseName(foreignKey))))
            {
                return(foreignKey.Builder);
            }

            var relationshipBuilder = foreignKey.Builder;

            using (var batch = foreignKey.DeclaringEntityType.Model.ConventionDispatcher.StartBatch())
            {
                var temporaryProperties = foreignKey.Properties.Where(
                    p => p.IsShadowProperty() &&
                    ConfigurationSource.Convention.Overrides(p.GetConfigurationSource())).ToList();

                var keysToDetach = temporaryProperties.SelectMany(
                    p => p.GetContainingKeys()
                    .Where(k => ConfigurationSource.Convention.Overrides(k.GetConfigurationSource())))
                                   .Distinct().ToList();

                List <RelationshipSnapshot> detachedRelationships = null;
                foreach (var key in keysToDetach)
                {
                    foreach (var referencingForeignKey in key.GetReferencingForeignKeys().ToList())
                    {
                        if (detachedRelationships == null)
                        {
                            detachedRelationships = new List <RelationshipSnapshot>();
                        }

                        detachedRelationships.Add(InternalEntityTypeBuilder.DetachRelationship(referencingForeignKey));
                    }
                }

                var detachedKeys = InternalEntityTypeBuilder.DetachKeys(keysToDetach);

                var detachedIndexes = InternalEntityTypeBuilder.DetachIndexes(
                    temporaryProperties.SelectMany(p => p.GetContainingIndexes()).Distinct());

                relationshipBuilder = relationshipBuilder.HasForeignKey((IReadOnlyList <Property>)null, ConfigurationSource.Convention);

                if (detachedIndexes != null)
                {
                    foreach (var indexBuilderTuple in detachedIndexes)
                    {
                        indexBuilderTuple.Attach(indexBuilderTuple.Metadata.DeclaringEntityType.Builder);
                    }
                }

                if (detachedKeys != null)
                {
                    foreach (var detachedKeyTuple in detachedKeys)
                    {
                        detachedKeyTuple.Item1.Attach(foreignKey.DeclaringEntityType.RootType().Builder, detachedKeyTuple.Item2);
                    }
                }

                if (detachedRelationships != null)
                {
                    foreach (var detachedRelationship in detachedRelationships)
                    {
                        detachedRelationship.Attach();
                    }
                }

                return(batch.Run(relationshipBuilder));
            }
        }
Exemplo n.º 57
0
 private void SetInverseNavigations(
     InternalEntityTypeBuilder entityTypeBuilder,
     Dictionary <PropertyInfo, List <Tuple <PropertyInfo, Type> > > inverseNavigations)
 => entityTypeBuilder.HasAnnotation(InverseNavigationsAnnotationName, inverseNavigations, ConfigurationSource.Convention);
        public virtual bool Apply(
            InternalEntityTypeBuilder sourceEntityTypeBuilder,
            InternalEntityTypeBuilder targetEntityTypeBuilder,
            string navigationName)
        {
            if (sourceEntityTypeBuilder.IsIgnored(navigationName, ConfigurationSource.Convention))
            {
                return true;
            }

            Apply(sourceEntityTypeBuilder);

            foreach (var derivedType in sourceEntityTypeBuilder.Metadata.GetDerivedTypes())
            {
                Apply(sourceEntityTypeBuilder.ModelBuilder.Entity(derivedType.Name, ConfigurationSource.Convention));
            }

            return true;
        }
 /// <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 InternalEntityTypeBuilder OnBaseEntityTypeChanged(
     [NotNull] InternalEntityTypeBuilder entityTypeBuilder,
     [CanBeNull] EntityType previousBaseType)
 => _scope.OnBaseEntityTypeChanged(Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder)), previousBaseType);
 private static void ConfigureKeys(InternalEntityTypeBuilder entityTypeBuilder)
 {
     entityTypeBuilder.PrimaryKey(new[] { "Id" }, ConfigurationSource.Convention);
 }