private static ForeignKey?CreateSkipNavigationForeignKey( SkipNavigation skipNavigation, InternalEntityTypeBuilder joinEntityTypeBuilder) => joinEntityTypeBuilder .HasRelationship( skipNavigation.DeclaringEntityType, ConfigurationSource.Convention, required: true, skipNavigation.Inverse !.Name) !
private static ForeignKey CreateSkipNavigationForeignKey( SkipNavigation skipNavigation, InternalEntityTypeBuilder joinEntityTypeBuilder) => joinEntityTypeBuilder .HasRelationship( skipNavigation.DeclaringEntityType, ConfigurationSource.Convention, required: true) .IsUnique(false, ConfigurationSource.Convention) .Metadata;
private static ForeignKey CreateSkipNavigationForeignKey( SkipNavigation skipNavigation, InternalEntityTypeBuilder associationEntityTypeBuilder) { var principalEntityType = skipNavigation.DeclaringEntityType; var principalKey = principalEntityType.FindPrimaryKey(); if (principalKey == null) { return(null); } var dependentEndForeignKeyPropertyNames = new List <string>(); var otherIdentifiers = associationEntityTypeBuilder.Metadata .GetDeclaredProperties().ToDictionary(p => p.Name, p => 0); foreach (var property in principalKey.Properties) { var propertyName = Uniquifier.Uniquify( string.Format( AssociationPropertyNameTemplate, principalEntityType.ShortName(), property.Name), otherIdentifiers, int.MaxValue); dependentEndForeignKeyPropertyNames.Add(propertyName); otherIdentifiers.Add(propertyName, 0); } return(associationEntityTypeBuilder .HasRelationship( principalEntityType.Name, dependentEndForeignKeyPropertyNames, principalKey, ConfigurationSource.Convention) .IsUnique(false, ConfigurationSource.Convention) .Metadata); }
private InternalRelationshipBuilder ConfigureInverseNavigation( InternalEntityTypeBuilder entityTypeBuilder, MemberInfo navigationMemberInfo, InternalEntityTypeBuilder targetEntityTypeBuilder, InversePropertyAttribute attribute) { var entityType = entityTypeBuilder.Metadata; var targetClrType = targetEntityTypeBuilder.Metadata.ClrType; var inverseNavigationPropertyInfo = targetEntityTypeBuilder.Metadata.GetRuntimeProperties().Values .FirstOrDefault(p => string.Equals(p.GetSimpleMemberName(), attribute.Property, StringComparison.OrdinalIgnoreCase)); if (inverseNavigationPropertyInfo == null || !FindCandidateNavigationPropertyType(inverseNavigationPropertyInfo).GetTypeInfo() .IsAssignableFrom(entityType.ClrType.GetTypeInfo())) { throw new InvalidOperationException( CoreStrings.InvalidNavigationWithInverseProperty( navigationMemberInfo.Name, entityType.DisplayName(), attribute.Property, targetClrType.ShortDisplayName())); } if (Equals(inverseNavigationPropertyInfo, navigationMemberInfo)) { throw new InvalidOperationException( CoreStrings.SelfReferencingNavigationWithInverseProperty( navigationMemberInfo.Name, entityType.DisplayName(), navigationMemberInfo.Name, entityType.DisplayName())); } // Check for InversePropertyAttribute on the inverseNavigation to verify that it matches. if (Attribute.IsDefined(inverseNavigationPropertyInfo, typeof(InversePropertyAttribute))) { var inverseAttribute = inverseNavigationPropertyInfo.GetCustomAttribute <InversePropertyAttribute>(true); if (inverseAttribute.Property != navigationMemberInfo.GetSimpleMemberName()) { throw new InvalidOperationException( CoreStrings.InversePropertyMismatch( navigationMemberInfo.Name, entityType.DisplayName(), inverseNavigationPropertyInfo.Name, targetEntityTypeBuilder.Metadata.DisplayName())); } } var referencingNavigationsWithAttribute = AddInverseNavigation(entityType, navigationMemberInfo, targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo); var ambiguousInverse = FindAmbiguousInverse( navigationMemberInfo, entityType, entityType.Model, referencingNavigationsWithAttribute); if (ambiguousInverse != null) { var existingInverse = targetEntityTypeBuilder.Metadata.FindNavigation(inverseNavigationPropertyInfo)?.FindInverse(); var existingInverseType = existingInverse?.DeclaringEntityType; if (existingInverse != null && IsAmbiguousInverse( existingInverse.GetIdentifyingMemberInfo(), existingInverseType, entityType.Model, referencingNavigationsWithAttribute)) { var fk = existingInverse.ForeignKey; if (fk.IsOwnership || fk.DeclaringEntityType.Builder.RemoveForeignKey(fk, ConfigurationSource.DataAnnotation) == null) { fk.Builder.HasNavigations( existingInverse.IsDependentToPrincipal() ? PropertyIdentity.None : (PropertyIdentity?)null, existingInverse.IsDependentToPrincipal() ? (PropertyIdentity?)null : PropertyIdentity.None, ConfigurationSource.DataAnnotation); } } var existingNavigation = entityType.FindNavigation(navigationMemberInfo); if (existingNavigation != null) { var fk = existingNavigation.ForeignKey; if (fk.IsOwnership || fk.DeclaringEntityType.Builder.RemoveForeignKey(fk, ConfigurationSource.DataAnnotation) == null) { fk.Builder.HasNavigations( existingNavigation.IsDependentToPrincipal() ? PropertyIdentity.None : (PropertyIdentity?)null, existingNavigation.IsDependentToPrincipal() ? (PropertyIdentity?)null : PropertyIdentity.None, ConfigurationSource.DataAnnotation); } } var existingAmbiguousNavigation = entityType.Model.FindActualEntityType(ambiguousInverse.Value.Item2) .FindNavigation(ambiguousInverse.Value.Item1); if (existingAmbiguousNavigation != null) { var fk = existingAmbiguousNavigation.ForeignKey; if (fk.IsOwnership || fk.DeclaringEntityType.Builder.RemoveForeignKey(fk, ConfigurationSource.DataAnnotation) == null) { fk.Builder.HasNavigations( existingAmbiguousNavigation.IsDependentToPrincipal() ? PropertyIdentity.None : (PropertyIdentity?)null, existingAmbiguousNavigation.IsDependentToPrincipal() ? (PropertyIdentity?)null : PropertyIdentity.None, ConfigurationSource.DataAnnotation); } } return(entityType.FindNavigation(navigationMemberInfo)?.ForeignKey.Builder); } var ownership = entityType.FindOwnership(); if (ownership != null && ownership.PrincipalEntityType == targetEntityTypeBuilder.Metadata && ownership.PrincipalToDependent?.GetIdentifyingMemberInfo() != inverseNavigationPropertyInfo) { Logger.NonOwnershipInverseNavigationWarning( entityType, navigationMemberInfo, targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo, ownership.PrincipalToDependent.GetIdentifyingMemberInfo()); return(null); } if (entityType.DefiningEntityType != null && entityType.DefiningEntityType == targetEntityTypeBuilder.Metadata && entityType.DefiningNavigationName != inverseNavigationPropertyInfo.GetSimpleMemberName()) { Logger.NonDefiningInverseNavigationWarning( entityType, navigationMemberInfo, targetEntityTypeBuilder.Metadata, inverseNavigationPropertyInfo, entityType.DefiningEntityType.GetRuntimeProperties()[entityType.DefiningNavigationName]); return(null); } return(entityType.Model.ShouldBeOwned(entityType.ClrType) && !entityType.IsInOwnershipPath(targetEntityTypeBuilder.Metadata) ? targetEntityTypeBuilder.HasOwnership( entityTypeBuilder.Metadata.ClrType, inverseNavigationPropertyInfo, navigationMemberInfo, ConfigurationSource.Convention) : targetEntityTypeBuilder.HasRelationship( entityType, inverseNavigationPropertyInfo, navigationMemberInfo, ConfigurationSource.DataAnnotation)); }