public void InversePropertyAttribute_does_not_override_configuration_from_explicit_source() { var dependentEntityTypeBuilder = CreateInternalEntityTypeBuilder <Dependent>(); var principalEntityTypeBuilder = dependentEntityTypeBuilder.ModelBuilder.Entity(typeof(Principal), ConfigurationSource.Convention); dependentEntityTypeBuilder.Relationship( principalEntityTypeBuilder, nameof(Dependent.Principal), nameof(Principal.Dependents), ConfigurationSource.Explicit); Assert.Contains(principalEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(Principal.Dependents)); Assert.DoesNotContain(principalEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(Principal.Dependent)); Assert.Contains(dependentEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(Dependent.Principal)); var convention = new InversePropertyAttributeConvention(CreateTypeMapper(), CreateLogger()); new InversePropertyAttributeConvention(CreateTypeMapper(), CreateLogger()).Apply(dependentEntityTypeBuilder); Assert.Contains(principalEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(Principal.Dependents)); Assert.DoesNotContain(principalEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(Principal.Dependent)); Assert.Contains(dependentEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(Dependent.Principal)); convention.Apply(dependentEntityTypeBuilder.ModelBuilder); }
public void InversePropertyAttribute_does_not_configure_ambiguous_navigations() { var dependentEntityTypeBuilder = CreateInternalEntityTypeBuilder <AmbiguousDependent>(); var principalEntityTypeBuilder = dependentEntityTypeBuilder.ModelBuilder.Entity(typeof(AmbiguousPrincipal), ConfigurationSource.Convention); dependentEntityTypeBuilder.Relationship( principalEntityTypeBuilder, nameof(AmbiguousDependent.AmbiguousPrincipal), nameof(AmbiguousPrincipal.Dependent), ConfigurationSource.Convention); Assert.Contains(principalEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(AmbiguousPrincipal.Dependent)); Assert.Contains(dependentEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(AmbiguousDependent.AmbiguousPrincipal)); Assert.DoesNotContain(dependentEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(AmbiguousDependent.AnotherAmbiguousPrincipal)); var convention = new InversePropertyAttributeConvention(CreateTypeMapper(), CreateLogger()); convention.Apply(dependentEntityTypeBuilder); Assert.DoesNotContain(principalEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(AmbiguousPrincipal.Dependent)); Assert.DoesNotContain(dependentEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(AmbiguousDependent.AnotherAmbiguousPrincipal)); Assert.DoesNotContain(dependentEntityTypeBuilder.Metadata.GetNavigations(), nav => nav.Name == nameof(AmbiguousDependent.AmbiguousPrincipal)); convention.Apply(dependentEntityTypeBuilder.ModelBuilder); Assert.Equal(1, Log.Count); Assert.Equal(LogLevel.Information, Log[0].Level); Assert.Equal(CoreStrings.LogMultipleInversePropertiesSameTarget.GenerateMessage( "AmbiguousDependent.AmbiguousPrincipal, AmbiguousDependent.AnotherAmbiguousPrincipal", nameof(AmbiguousPrincipal.Dependent)), Log[0].Message); }
private void CreateRelationships( IReadOnlyList <RelationshipCandidate> relationshipCandidates, InternalEntityTypeBuilder entityTypeBuilder) { var unusedEntityTypes = new List <EntityType>(); foreach (var relationshipCandidate in relationshipCandidates) { Debug.Assert(relationshipCandidate.NavigationProperties.Count > 0); 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) || relationshipCandidate.InverseProperties.Count > 1 || isAmbiguousOnBase) { if (!isAmbiguousOnBase) { AddAmbiguous(entityTypeBuilder, relationshipCandidate.NavigationProperties, targetEntityType.ClrType); AddAmbiguous(relationshipCandidate.TargetTypeBuilder, relationshipCandidate.InverseProperties, entityType.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) { continue; } if (InversePropertyAttributeConvention.IsAmbiguous(entityType, navigation, targetEntityType)) { unusedEntityTypes.Add(targetEntityType); continue; } var inverse = relationshipCandidate.InverseProperties.SingleOrDefault(); if (inverse == null) { entityTypeBuilder.Navigation( relationshipCandidate.TargetTypeBuilder, navigation, ConfigurationSource.Convention); } else { if (InversePropertyAttributeConvention.IsAmbiguous(targetEntityType, inverse, entityType)) { unusedEntityTypes.Add(targetEntityType); continue; } entityTypeBuilder.Relationship( targetEntityType.Builder, navigation, inverse, ConfigurationSource.Convention); } } } foreach (var unusedEntityType in unusedEntityTypes) { if (unusedEntityType.HasDelegatedIdentity() && unusedEntityType.DefiningEntityType.FindNavigation(unusedEntityType.DefiningNavigationName) == null) { entityTypeBuilder.ModelBuilder. RemoveDelegatedIdentityEntityType(unusedEntityType, 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 ConventionSet CreateConventionSet(DiagnosticsLoggers loggers) { var conventionSet = new ConventionSet(); var logger = loggers.GetLogger <DbLoggerCategory.Model>(); var propertyDiscoveryConvention = new PropertyDiscoveryConvention( Dependencies.TypeMappingSource, logger); var keyDiscoveryConvention = new KeyDiscoveryConvention(logger); var inversePropertyAttributeConvention = new InversePropertyAttributeConvention(Dependencies.MemberClassifier, logger); var relationshipDiscoveryConvention = new RelationshipDiscoveryConvention(Dependencies.MemberClassifier, logger); var servicePropertyDiscoveryConvention = new ServicePropertyDiscoveryConvention(Dependencies.TypeMappingSource, Dependencies.ParameterBindingFactories, logger); conventionSet.EntityTypeAddedConventions.Add(new NotMappedEntityTypeAttributeConvention(logger)); conventionSet.EntityTypeAddedConventions.Add(new OwnedEntityTypeAttributeConvention(logger)); conventionSet.EntityTypeAddedConventions.Add(new NotMappedMemberAttributeConvention(logger)); conventionSet.EntityTypeAddedConventions.Add(new BaseTypeDiscoveryConvention(logger)); conventionSet.EntityTypeAddedConventions.Add(propertyDiscoveryConvention); conventionSet.EntityTypeAddedConventions.Add(servicePropertyDiscoveryConvention); conventionSet.EntityTypeAddedConventions.Add(keyDiscoveryConvention); conventionSet.EntityTypeAddedConventions.Add(inversePropertyAttributeConvention); conventionSet.EntityTypeAddedConventions.Add(relationshipDiscoveryConvention); conventionSet.EntityTypeAddedConventions.Add(new DerivedTypeDiscoveryConvention(logger)); conventionSet.EntityTypeIgnoredConventions.Add(inversePropertyAttributeConvention); conventionSet.EntityTypeRemovedConventions.Add(new OwnedTypesConvention(logger)); var foreignKeyIndexConvention = new ForeignKeyIndexConvention(logger); var valueGeneratorConvention = new ValueGeneratorConvention(logger); conventionSet.BaseEntityTypeChangedConventions.Add(propertyDiscoveryConvention); conventionSet.BaseEntityTypeChangedConventions.Add(servicePropertyDiscoveryConvention); conventionSet.BaseEntityTypeChangedConventions.Add(keyDiscoveryConvention); conventionSet.BaseEntityTypeChangedConventions.Add(inversePropertyAttributeConvention); conventionSet.BaseEntityTypeChangedConventions.Add(relationshipDiscoveryConvention); conventionSet.BaseEntityTypeChangedConventions.Add(foreignKeyIndexConvention); conventionSet.BaseEntityTypeChangedConventions.Add(valueGeneratorConvention); var foreignKeyPropertyDiscoveryConvention = new ForeignKeyPropertyDiscoveryConvention(logger); conventionSet.EntityTypeMemberIgnoredConventions.Add(inversePropertyAttributeConvention); conventionSet.EntityTypeMemberIgnoredConventions.Add(relationshipDiscoveryConvention); conventionSet.EntityTypeMemberIgnoredConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.EntityTypeMemberIgnoredConventions.Add(servicePropertyDiscoveryConvention); var keyAttributeConvention = new KeyAttributeConvention(logger); var backingFieldConvention = new BackingFieldConvention(logger); var concurrencyCheckAttributeConvention = new ConcurrencyCheckAttributeConvention(logger); var databaseGeneratedAttributeConvention = new DatabaseGeneratedAttributeConvention(logger); var requiredPropertyAttributeConvention = new RequiredPropertyAttributeConvention(logger); var maxLengthAttributeConvention = new MaxLengthAttributeConvention(logger); var stringLengthAttributeConvention = new StringLengthAttributeConvention(logger); var timestampAttributeConvention = new TimestampAttributeConvention(logger); conventionSet.PropertyAddedConventions.Add(backingFieldConvention); conventionSet.PropertyAddedConventions.Add(concurrencyCheckAttributeConvention); conventionSet.PropertyAddedConventions.Add(databaseGeneratedAttributeConvention); conventionSet.PropertyAddedConventions.Add(requiredPropertyAttributeConvention); conventionSet.PropertyAddedConventions.Add(maxLengthAttributeConvention); conventionSet.PropertyAddedConventions.Add(stringLengthAttributeConvention); conventionSet.PropertyAddedConventions.Add(timestampAttributeConvention); conventionSet.PropertyAddedConventions.Add(keyAttributeConvention); conventionSet.PropertyAddedConventions.Add(keyDiscoveryConvention); conventionSet.PropertyAddedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.PrimaryKeyChangedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.PrimaryKeyChangedConventions.Add(valueGeneratorConvention); conventionSet.KeyAddedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.KeyAddedConventions.Add(foreignKeyIndexConvention); conventionSet.KeyRemovedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.KeyRemovedConventions.Add(foreignKeyIndexConvention); conventionSet.KeyRemovedConventions.Add(keyDiscoveryConvention); var cascadeDeleteConvention = new CascadeDeleteConvention(logger); var foreignKeyAttributeConvention = new ForeignKeyAttributeConvention(Dependencies.MemberClassifier, logger); conventionSet.ForeignKeyAddedConventions.Add(foreignKeyAttributeConvention); conventionSet.ForeignKeyAddedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.ForeignKeyAddedConventions.Add(keyDiscoveryConvention); conventionSet.ForeignKeyAddedConventions.Add(valueGeneratorConvention); conventionSet.ForeignKeyAddedConventions.Add(cascadeDeleteConvention); conventionSet.ForeignKeyAddedConventions.Add(foreignKeyIndexConvention); conventionSet.ForeignKeyRemovedConventions.Add(keyDiscoveryConvention); conventionSet.ForeignKeyRemovedConventions.Add(valueGeneratorConvention); conventionSet.ForeignKeyRemovedConventions.Add(foreignKeyIndexConvention); conventionSet.ForeignKeyUniquenessChangedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.ForeignKeyUniquenessChangedConventions.Add(keyDiscoveryConvention); conventionSet.ForeignKeyUniquenessChangedConventions.Add(foreignKeyIndexConvention); conventionSet.ForeignKeyRequirednessChangedConventions.Add(cascadeDeleteConvention); conventionSet.ForeignKeyRequirednessChangedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.ForeignKeyOwnershipChangedConventions.Add(new NavigationEagerLoadingConvention(logger)); conventionSet.ForeignKeyOwnershipChangedConventions.Add(keyDiscoveryConvention); conventionSet.ForeignKeyOwnershipChangedConventions.Add(relationshipDiscoveryConvention); conventionSet.ModelBuiltConventions.Add(new ModelCleanupConvention(logger)); conventionSet.ModelBuiltConventions.Add(keyAttributeConvention); conventionSet.ModelBuiltConventions.Add(foreignKeyAttributeConvention); conventionSet.ModelBuiltConventions.Add(new ChangeTrackingStrategyConvention(logger)); conventionSet.ModelBuiltConventions.Add(new ConstructorBindingConvention(Dependencies.ConstructorBindingFactory, logger)); conventionSet.ModelBuiltConventions.Add(new TypeMappingConvention(Dependencies.TypeMappingSource, logger)); conventionSet.ModelBuiltConventions.Add(new IgnoredMembersValidationConvention(logger)); conventionSet.ModelBuiltConventions.Add(foreignKeyIndexConvention); conventionSet.ModelBuiltConventions.Add( new PropertyMappingValidationConvention( Dependencies.TypeMappingSource, Dependencies.MemberClassifier, logger)); conventionSet.ModelBuiltConventions.Add(new RelationshipValidationConvention(logger)); conventionSet.ModelBuiltConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.ModelBuiltConventions.Add(servicePropertyDiscoveryConvention); conventionSet.ModelBuiltConventions.Add(new CacheCleanupConvention(logger)); conventionSet.NavigationAddedConventions.Add(backingFieldConvention); conventionSet.NavigationAddedConventions.Add(new RequiredNavigationAttributeConvention(logger)); conventionSet.NavigationAddedConventions.Add(inversePropertyAttributeConvention); conventionSet.NavigationAddedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.NavigationAddedConventions.Add(relationshipDiscoveryConvention); conventionSet.NavigationRemovedConventions.Add(relationshipDiscoveryConvention); conventionSet.IndexAddedConventions.Add(foreignKeyIndexConvention); conventionSet.IndexRemovedConventions.Add(foreignKeyIndexConvention); conventionSet.IndexUniquenessChangedConventions.Add(foreignKeyIndexConvention); conventionSet.PrincipalEndChangedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.PropertyNullabilityChangedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.PropertyFieldChangedConventions.Add(keyDiscoveryConvention); conventionSet.PropertyFieldChangedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.PropertyFieldChangedConventions.Add(keyAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(concurrencyCheckAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(databaseGeneratedAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(requiredPropertyAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(maxLengthAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(stringLengthAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(timestampAttributeConvention); return(conventionSet); }
/// <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 ConventionSet CreateConventionSet() { var conventionSet = new ConventionSet(); var propertyDiscoveryConvention = new PropertyDiscoveryConvention(Dependencies.TypeMapper); var keyDiscoveryConvention = new KeyDiscoveryConvention(); var inversePropertyAttributeConvention = new InversePropertyAttributeConvention(Dependencies.TypeMapper); var relationshipDiscoveryConvention = new RelationshipDiscoveryConvention(Dependencies.TypeMapper); conventionSet.EntityTypeAddedConventions.Add(new NotMappedEntityTypeAttributeConvention()); conventionSet.EntityTypeAddedConventions.Add(new OwnedEntityTypeAttributeConvention()); conventionSet.EntityTypeAddedConventions.Add(new NotMappedMemberAttributeConvention()); conventionSet.EntityTypeAddedConventions.Add(new BaseTypeDiscoveryConvention()); conventionSet.EntityTypeAddedConventions.Add(propertyDiscoveryConvention); conventionSet.EntityTypeAddedConventions.Add(keyDiscoveryConvention); conventionSet.EntityTypeAddedConventions.Add(inversePropertyAttributeConvention); conventionSet.EntityTypeAddedConventions.Add(relationshipDiscoveryConvention); conventionSet.EntityTypeAddedConventions.Add(new DerivedTypeDiscoveryConvention()); conventionSet.EntityTypeIgnoredConventions.Add(inversePropertyAttributeConvention); var foreignKeyIndexConvention = new ForeignKeyIndexConvention(); var valueGeneratorConvention = new ValueGeneratorConvention(); conventionSet.BaseEntityTypeChangedConventions.Add(propertyDiscoveryConvention); conventionSet.BaseEntityTypeChangedConventions.Add(keyDiscoveryConvention); conventionSet.BaseEntityTypeChangedConventions.Add(inversePropertyAttributeConvention); conventionSet.BaseEntityTypeChangedConventions.Add(relationshipDiscoveryConvention); conventionSet.BaseEntityTypeChangedConventions.Add(foreignKeyIndexConvention); conventionSet.BaseEntityTypeChangedConventions.Add(valueGeneratorConvention); // An ambiguity might have been resolved conventionSet.EntityTypeMemberIgnoredConventions.Add(inversePropertyAttributeConvention); conventionSet.EntityTypeMemberIgnoredConventions.Add(relationshipDiscoveryConvention); var keyAttributeConvention = new KeyAttributeConvention(); var foreignKeyPropertyDiscoveryConvention = new ForeignKeyPropertyDiscoveryConvention(); var backingFieldConvention = new BackingFieldConvention(); var concurrencyCheckAttributeConvention = new ConcurrencyCheckAttributeConvention(); var databaseGeneratedAttributeConvention = new DatabaseGeneratedAttributeConvention(); var requiredPropertyAttributeConvention = new RequiredPropertyAttributeConvention(); var maxLengthAttributeConvention = new MaxLengthAttributeConvention(); var stringLengthAttributeConvention = new StringLengthAttributeConvention(); var timestampAttributeConvention = new TimestampAttributeConvention(); conventionSet.PropertyAddedConventions.Add(backingFieldConvention); conventionSet.PropertyAddedConventions.Add(concurrencyCheckAttributeConvention); conventionSet.PropertyAddedConventions.Add(databaseGeneratedAttributeConvention); conventionSet.PropertyAddedConventions.Add(requiredPropertyAttributeConvention); conventionSet.PropertyAddedConventions.Add(maxLengthAttributeConvention); conventionSet.PropertyAddedConventions.Add(stringLengthAttributeConvention); conventionSet.PropertyAddedConventions.Add(timestampAttributeConvention); conventionSet.PropertyAddedConventions.Add(keyDiscoveryConvention); conventionSet.PropertyAddedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.PropertyAddedConventions.Add(keyAttributeConvention); conventionSet.PrimaryKeyChangedConventions.Add(valueGeneratorConvention); conventionSet.KeyAddedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.KeyAddedConventions.Add(foreignKeyIndexConvention); conventionSet.KeyRemovedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.KeyRemovedConventions.Add(foreignKeyIndexConvention); conventionSet.KeyRemovedConventions.Add(keyDiscoveryConvention); var cascadeDeleteConvention = new CascadeDeleteConvention(); conventionSet.ForeignKeyAddedConventions.Add(new ForeignKeyAttributeConvention(Dependencies.TypeMapper)); conventionSet.ForeignKeyAddedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.ForeignKeyAddedConventions.Add(keyDiscoveryConvention); conventionSet.ForeignKeyAddedConventions.Add(valueGeneratorConvention); conventionSet.ForeignKeyAddedConventions.Add(cascadeDeleteConvention); conventionSet.ForeignKeyAddedConventions.Add(foreignKeyIndexConvention); conventionSet.ForeignKeyRemovedConventions.Add(keyDiscoveryConvention); conventionSet.ForeignKeyRemovedConventions.Add(valueGeneratorConvention); conventionSet.ForeignKeyRemovedConventions.Add(foreignKeyIndexConvention); conventionSet.ForeignKeyUniquenessChangedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.ForeignKeyUniquenessChangedConventions.Add(foreignKeyIndexConvention); conventionSet.ForeignKeyOwnershipChangedConventions.Add(new NavigationEagerLoadingConvention()); conventionSet.ModelBuiltConventions.Add(new ModelCleanupConvention()); conventionSet.ModelBuiltConventions.Add(keyAttributeConvention); conventionSet.ModelBuiltConventions.Add(new IgnoredMembersValidationConvention()); conventionSet.ModelBuiltConventions.Add(new PropertyMappingValidationConvention(Dependencies.TypeMapper)); conventionSet.ModelBuiltConventions.Add(new RelationshipValidationConvention()); conventionSet.ModelBuiltConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.ModelBuiltConventions.Add(new ChangeTrackingStrategyConvention()); conventionSet.ModelBuiltConventions.Add(new ConstructorBindingConvention(Dependencies.ConstructorBindingFactory)); conventionSet.NavigationAddedConventions.Add(backingFieldConvention); conventionSet.NavigationAddedConventions.Add(new RequiredNavigationAttributeConvention()); conventionSet.NavigationAddedConventions.Add(inversePropertyAttributeConvention); conventionSet.NavigationAddedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.NavigationAddedConventions.Add(relationshipDiscoveryConvention); conventionSet.NavigationRemovedConventions.Add(relationshipDiscoveryConvention); conventionSet.IndexAddedConventions.Add(foreignKeyIndexConvention); conventionSet.IndexRemovedConventions.Add(foreignKeyIndexConvention); conventionSet.IndexUniquenessChangedConventions.Add(foreignKeyIndexConvention); conventionSet.PropertyNullabilityChangedConventions.Add(cascadeDeleteConvention); conventionSet.PrincipalEndChangedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.PropertyFieldChangedConventions.Add(keyDiscoveryConvention); conventionSet.PropertyFieldChangedConventions.Add(foreignKeyPropertyDiscoveryConvention); conventionSet.PropertyFieldChangedConventions.Add(keyAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(concurrencyCheckAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(databaseGeneratedAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(requiredPropertyAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(maxLengthAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(stringLengthAttributeConvention); conventionSet.PropertyFieldChangedConventions.Add(timestampAttributeConvention); return(conventionSet); }
private static 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 || relationshipCandidate.InverseProperties.Count > 1 || isAmbiguousOnBase) { if (!isAmbiguousOnBase) { AddAmbiguous(entityTypeBuilder, relationshipCandidate.NavigationProperties, targetEntityType.ClrType); AddAmbiguous(targetEntityType.Builder, relationshipCandidate.InverseProperties, entityType.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) { continue; } if (InversePropertyAttributeConvention.IsAmbiguous(entityType, navigation, targetEntityType)) { unusedEntityTypes.Add(targetEntityType); continue; } var inverse = relationshipCandidate.InverseProperties.SingleOrDefault(); if (inverse == null) { if (targetEntityType.DefiningNavigationName == navigation.Name && targetEntityType.DefiningEntityType == entityType && targetEntityType.Model.ShouldBeOwnedType(targetEntityType.ClrType)) { 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.DefiningNavigationName == navigation.Name && targetEntityType.DefiningEntityType == entityType && targetEntityType.Model.ShouldBeOwnedType(targetEntityType.ClrType)) { 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); } } }
private void CreateRelationships( IReadOnlyList <RelationshipCandidate> relationshipCandidates, InternalEntityTypeBuilder entityTypeBuilder) { foreach (var relationshipCandidate in relationshipCandidates) { Debug.Assert(relationshipCandidate.NavigationProperties.Count > 0); var isAmbiguousOnBase = (entityTypeBuilder.Metadata.BaseType != null && HasAmbiguousNavigationsTo( entityTypeBuilder.Metadata.BaseType, relationshipCandidate.TargetTypeBuilder.Metadata.ClrType)) || (relationshipCandidate.TargetTypeBuilder.Metadata.BaseType != null && HasAmbiguousNavigationsTo( relationshipCandidate.TargetTypeBuilder.Metadata.BaseType, entityTypeBuilder.Metadata.ClrType)); if ((relationshipCandidate.NavigationProperties.Count > 1 && relationshipCandidate.InverseProperties.Count > 0) || relationshipCandidate.InverseProperties.Count > 1 || isAmbiguousOnBase) { if (!isAmbiguousOnBase) { AddAmbiguous(entityTypeBuilder, relationshipCandidate.NavigationProperties, relationshipCandidate.TargetTypeBuilder.Metadata.ClrType); AddAmbiguous(relationshipCandidate.TargetTypeBuilder, relationshipCandidate.InverseProperties, entityTypeBuilder.Metadata.ClrType); } foreach (var navigationProperty in relationshipCandidate.NavigationProperties) { var existingForeignKey = entityTypeBuilder.Metadata.FindDeclaredNavigation(navigationProperty.Name)?.ForeignKey; existingForeignKey?.DeclaringEntityType.Builder .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention); } foreach (var inverseProperty in relationshipCandidate.InverseProperties) { var existingForeignKey = relationshipCandidate.TargetTypeBuilder.Metadata .FindDeclaredNavigation(inverseProperty.Name)?.ForeignKey; existingForeignKey?.DeclaringEntityType.Builder .RemoveForeignKey(existingForeignKey, ConfigurationSource.Convention); } continue; } foreach (var navigation in relationshipCandidate.NavigationProperties) { if (InversePropertyAttributeConvention.IsAmbiguous( entityTypeBuilder.Metadata, navigation, relationshipCandidate.TargetTypeBuilder.Metadata)) { continue; } var inverse = relationshipCandidate.InverseProperties.SingleOrDefault(); if (inverse == null) { entityTypeBuilder.Navigation( relationshipCandidate.TargetTypeBuilder, navigation, ConfigurationSource.Convention); } else { if (InversePropertyAttributeConvention.IsAmbiguous( relationshipCandidate.TargetTypeBuilder.Metadata, inverse, entityTypeBuilder.Metadata)) { continue; } entityTypeBuilder.Relationship( relationshipCandidate.TargetTypeBuilder, navigation, inverse, ConfigurationSource.Convention); } } } }