/// <summary> /// <para> /// Initializes a new instance of the <see cref="ReferenceCollectionBuilder" /> class. /// </para> /// </summary> /// <param name="builder"> The internal builder being used to configure this relationship. </param> /// <param name="oldBuilder"> A builder to copy configuration from. </param> /// <param name="foreignKeySet"> /// A value indicating whether the foreign key properties have been configured in this chain of configuration calls. /// </param> /// <param name="principalKeySet"> /// A value indicating whether the principal key properties have been configured in this chain of configuration calls. /// </param> /// <param name="requiredSet"> /// A value indicating whether required/optional has been configured in this chain of configuration calls. /// </param> protected ReferenceCollectionBuilder(InternalRelationshipBuilder builder, ReferenceCollectionBuilder oldBuilder, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) { Check.NotNull(builder, nameof(builder)); Builder = builder; if (oldBuilder != null) { _foreignKeyProperties = foreignKeySet ? builder.Metadata.Properties : oldBuilder._foreignKeyProperties; _principalKeyProperties = principalKeySet ? builder.Metadata.PrincipalKey.Properties : oldBuilder._principalKeyProperties; _required = requiredSet ? builder.Metadata.IsRequired : oldBuilder._required; var foreignKey = builder.Metadata; ForeignKey.AreCompatible( foreignKey.PrincipalEntityType, foreignKey.DeclaringEntityType, foreignKey.DependentToPrincipal?.Name, foreignKey.PrincipalToDependent?.Name, _foreignKeyProperties, _principalKeyProperties, foreignKey.IsUnique, _required, shouldThrow: true); } }
protected RelationshipBuilderBase( [NotNull] InternalForeignKeyBuilder builder, [NotNull] RelationshipBuilderBase oldBuilder, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) { Check.NotNull(builder, nameof(builder)); Builder = builder; PrincipalEntityType = oldBuilder.PrincipalEntityType; DependentEntityType = oldBuilder.DependentEntityType; _foreignKeyProperties = foreignKeySet ? builder.Metadata.Properties : ((EntityType)oldBuilder.DependentEntityType).Builder.GetActualProperties(oldBuilder._foreignKeyProperties, null); _principalKeyProperties = principalKeySet ? builder.Metadata.PrincipalKey.Properties : ((EntityType)oldBuilder.PrincipalEntityType).Builder.GetActualProperties(oldBuilder._principalKeyProperties, null); _required = requiredSet ? builder.Metadata.IsRequired : oldBuilder._required; var foreignKey = builder.Metadata; ForeignKey.AreCompatible( (EntityType)oldBuilder.PrincipalEntityType, (EntityType)oldBuilder.DependentEntityType, foreignKey.DependentToPrincipal?.GetIdentifyingMemberInfo(), foreignKey.PrincipalToDependent?.GetIdentifyingMemberInfo(), _foreignKeyProperties, _principalKeyProperties, foreignKey.IsUnique, shouldThrow: true); }
private static IReadOnlyList <Property> GetCompatiblePrimaryKeyProperties(EntityType dependentEntityType, EntityType principalEntityType, IReadOnlyList <Property> propertiesToReference) { var dependentPkProperties = dependentEntityType.FindPrimaryKey()?.Properties; return((dependentPkProperties != null) && ForeignKey.AreCompatible( propertiesToReference, dependentPkProperties, principalEntityType, dependentEntityType, false) ? dependentPkProperties : null); }
/// <summary> /// <para> /// Initializes a new instance of the <see cref="ReferenceReferenceBuilder" /> class. /// </para> /// </summary> /// <param name="builder"> The internal builder being used to configure this relationship. </param> /// <param name="oldBuilder"> A builder to copy configuration from. </param> /// <param name="inverted"> /// A value indicating whether to reverse the direction of the relationship. /// </param> /// <param name="foreignKeySet"> /// A value indicating whether the foreign key properties have been configured in this chain of configuration calls. /// </param> /// <param name="principalKeySet"> /// A value indicating whether the principal key properties have been configured in this chain of configuration calls. /// </param> /// <param name="requiredSet"> /// A value indicating whether required/optional has been configured in this chain of configuration calls. /// </param> protected ReferenceReferenceBuilder( InternalRelationshipBuilder builder, ReferenceReferenceBuilder oldBuilder, bool inverted = false, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) { Builder = builder; if (oldBuilder != null) { if (inverted) { if ((oldBuilder._foreignKeyProperties != null) || (oldBuilder._principalKeyProperties != null)) { throw new InvalidOperationException(CoreStrings.RelationshipCannotBeInverted); } var navigationName = _navigationToDependentName; _navigationToDependentName = _navigationToPrincipalName; _navigationToPrincipalName = navigationName; } _foreignKeyProperties = foreignKeySet ? builder.Metadata.Properties : oldBuilder._foreignKeyProperties; _principalKeyProperties = principalKeySet ? builder.Metadata.PrincipalKey.Properties : oldBuilder._principalKeyProperties; _required = requiredSet ? builder.Metadata.IsRequired : oldBuilder._required; var foreignKey = builder.Metadata; ForeignKey.AreCompatible( foreignKey.PrincipalEntityType, foreignKey.DeclaringEntityType, _navigationToPrincipalName, _navigationToDependentName, _foreignKeyProperties, _principalKeyProperties, foreignKey.IsUnique, _required, shouldThrow: 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> protected ReferenceReferenceBuilderBase( InternalRelationshipBuilder builder, ReferenceReferenceBuilderBase oldBuilder, bool inverted = false, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) { Builder = builder; if (oldBuilder != null) { if (inverted) { if (oldBuilder._foreignKeyProperties != null || oldBuilder._principalKeyProperties != null) { throw new InvalidOperationException(CoreStrings.RelationshipCannotBeInverted); } } DeclaringEntityType = oldBuilder.DeclaringEntityType; RelatedEntityType = oldBuilder.RelatedEntityType; _foreignKeyProperties = foreignKeySet ? builder.Metadata.Properties : oldBuilder._foreignKeyProperties; _principalKeyProperties = principalKeySet ? builder.Metadata.PrincipalKey.Properties : oldBuilder._principalKeyProperties; _required = requiredSet ? builder.Metadata.IsRequired : oldBuilder._required; var foreignKey = builder.Metadata; ForeignKey.AreCompatible( foreignKey.PrincipalEntityType, foreignKey.DeclaringEntityType, foreignKey.DependentToPrincipal?.PropertyInfo, foreignKey.PrincipalToDependent?.PropertyInfo, _foreignKeyProperties, _principalKeyProperties, foreignKey.IsUnique, _required, shouldThrow: true); } }
private static IReadOnlyList <IConventionProperty>?GetCompatiblePrimaryKeyProperties( IConventionEntityType dependentEntityType, IConventionEntityType principalEntityType, IReadOnlyList <IConventionProperty> propertiesToReference) { var dependentPkProperties = dependentEntityType.FindPrimaryKey()?.Properties; return(dependentPkProperties != null && ForeignKey.AreCompatible( propertiesToReference, dependentPkProperties, principalEntityType, dependentEntityType, shouldThrow: false) ? dependentPkProperties : null); }
private IReadOnlyList <Property> GetCompatiblePrimaryKeyProperties(EntityType dependentEntityType, EntityType principalEntityType, IReadOnlyList <Property> propertiesToReference) { var dependentPkProperties = dependentEntityType.FindPrimaryKey()?.Properties; if (dependentPkProperties != null && ForeignKey.AreCompatible( propertiesToReference, dependentPkProperties, principalEntityType, dependentEntityType, shouldThrow: false)) { return(dependentPkProperties); } return(null); }
/// <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> protected ReferenceCollectionBuilderBase( InternalRelationshipBuilder builder, ReferenceCollectionBuilderBase oldBuilder, bool foreignKeySet = false, bool principalKeySet = false, bool requiredSet = false) { Check.NotNull(builder, nameof(builder)); Builder = builder; if (oldBuilder != null) { PrincipalEntityType = oldBuilder.PrincipalEntityType; DependentEntityType = oldBuilder.DependentEntityType; _foreignKeyProperties = foreignKeySet ? builder.Metadata.Properties : DependentEntityType.Builder.GetActualProperties(oldBuilder._foreignKeyProperties, null); _principalKeyProperties = principalKeySet ? builder.Metadata.PrincipalKey.Properties : PrincipalEntityType.Builder.GetActualProperties(oldBuilder._principalKeyProperties, null); _required = requiredSet ? builder.Metadata.IsRequired : oldBuilder._required; var foreignKey = builder.Metadata; ForeignKey.AreCompatible( PrincipalEntityType, DependentEntityType, foreignKey.DependentToPrincipal?.GetIdentifyingMemberInfo(), foreignKey.PrincipalToDependent?.GetIdentifyingMemberInfo(), _foreignKeyProperties, _principalKeyProperties, foreignKey.IsUnique, _required, true); } }
private bool TryFindMatchingProperties( IConventionForeignKey foreignKey, string baseName, bool onDependent, bool matchPk, out IReadOnlyList <IConventionProperty>?match) { match = null; var dependentEntityType = onDependent ? foreignKey.DeclaringEntityType : foreignKey.PrincipalEntityType; var principalEntityType = onDependent ? foreignKey.PrincipalEntityType : foreignKey.DeclaringEntityType; var propertiesToReference = onDependent ? foreignKey.PrincipalKey.Properties : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties; if (propertiesToReference == null) { return(false); } var foreignKeyProperties = new IConventionProperty[propertiesToReference.Count]; var matchFound = true; for (var i = 0; i < propertiesToReference.Count; i++) { var referencedProperty = propertiesToReference[i]; var property = TryGetProperty( dependentEntityType, baseName, referencedProperty.Name); if (property == null) { matchFound = false; continue; } foreignKeyProperties[i] = property; } if (!matchFound && propertiesToReference.Count == 1 && baseName.Length > 0) { var property = TryGetProperty( dependentEntityType, baseName, "Id"); if (property != null) { foreignKeyProperties[0] = property; matchFound = true; } } if (!matchFound) { return(false); } if (!ForeignKey.AreCompatible( propertiesToReference, foreignKeyProperties, principalEntityType, dependentEntityType, shouldThrow: false)) { if (propertiesToReference.All( p => !p.IsImplicitlyCreated() || p.GetConfigurationSource().Overrides(ConfigurationSource.DataAnnotation))) { var dependentNavigationSpec = onDependent ? foreignKey.DependentToPrincipal?.Name : foreignKey.PrincipalToDependent?.Name; dependentNavigationSpec = dependentEntityType.DisplayName() + (string.IsNullOrEmpty(dependentNavigationSpec) ? string.Empty : "." + dependentNavigationSpec); var principalNavigationSpec = onDependent ? foreignKey.PrincipalToDependent?.Name : foreignKey.DependentToPrincipal?.Name; principalNavigationSpec = principalEntityType.DisplayName() + (string.IsNullOrEmpty(principalNavigationSpec) ? string.Empty : "." + principalNavigationSpec); Dependencies.Logger.IncompatibleMatchingForeignKeyProperties( dependentNavigationSpec, principalNavigationSpec, foreignKeyProperties, propertiesToReference); } // Stop searching if match found, but is incompatible return(true); } foreach (var key in dependentEntityType.GetKeys()) { var isKeyContainedInForeignKey = true; // ReSharper disable once LoopCanBeConvertedToQuery // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < key.Properties.Count; i++) { if (!foreignKeyProperties.Contains(key.Properties[i])) { isKeyContainedInForeignKey = false; break; } } if (isKeyContainedInForeignKey && (!foreignKey.IsUnique || (key.IsPrimaryKey() && !matchPk))) { // Stop searching if match found, but is incompatible return(true); } } match = foreignKeyProperties; return(true); }
private bool TryFindMatchingProperties( ForeignKey foreignKey, string baseName, bool onDependent, bool matchPK, out IReadOnlyList <Property> match) { match = null; var dependentEntityType = onDependent ? foreignKey.DeclaringEntityType : foreignKey.PrincipalEntityType; var principalEntityType = onDependent ? foreignKey.PrincipalEntityType : foreignKey.DeclaringEntityType; var propertiesToReference = onDependent ? foreignKey.PrincipalKey.Properties : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties; if (propertiesToReference == null) { return(false); } var foreignKeyProperties = new Property[propertiesToReference.Count]; var matchFound = true; for (var i = 0; i < propertiesToReference.Count; i++) { var referencedProperty = propertiesToReference[i]; var property = TryGetProperty( dependentEntityType, baseName, referencedProperty.Name); if (property == null) { matchFound = false; continue; } foreignKeyProperties[i] = property; } if (!matchFound && propertiesToReference.Count == 1 && baseName.Length > 0) { var property = TryGetProperty( dependentEntityType, baseName, "Id"); if (property != null) { foreignKeyProperties[0] = property; matchFound = true; } } if (!matchFound) { return(false); } if (!ForeignKey.AreCompatible( propertiesToReference, foreignKeyProperties, principalEntityType, dependentEntityType, false)) { if (propertiesToReference.All( p => !p.IsShadowProperty || p.GetConfigurationSource().Overrides(ConfigurationSource.DataAnnotation))) { Logger.IncompatibleMatchingForeignKeyProperties(foreignKeyProperties, propertiesToReference); } // Stop searching if match found, but is incompatible return(true); } foreach (var key in dependentEntityType.GetKeys()) { var isKeyContainedInForeignKey = true; // ReSharper disable once LoopCanBeConvertedToQuery // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < key.Properties.Count; i++) { if (!foreignKeyProperties.Contains(key.Properties[i])) { isKeyContainedInForeignKey = false; break; } if (!foreignKey.IsUnique) { // Stop searching if match found, but is incompatible return(true); } } if (isKeyContainedInForeignKey && key.IsPrimaryKey() && !matchPK) { // Stop searching if match found, but is incompatible return(true); } } match = foreignKeyProperties; return(true); }
private IReadOnlyList <Property> FindMatchingNonShadowProperties( ForeignKey foreignKey, string baseName, bool onDependent) { var dependentEntityType = onDependent ? foreignKey.DeclaringEntityType : foreignKey.PrincipalEntityType; var principalEntityType = onDependent ? foreignKey.PrincipalEntityType : foreignKey.DeclaringEntityType; var propertiesToReference = onDependent ? foreignKey.PrincipalKey.Properties : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties; if (propertiesToReference == null) { return(null); } var foreignKeyProperties = new List <Property>(); foreach (IProperty referencedProperty in propertiesToReference) { var property = TryGetProperty(dependentEntityType, baseName + referencedProperty.Name, referencedProperty.ClrType.UnwrapNullableType()); if (property != null) { foreignKeyProperties.Add(property); } } if ((propertiesToReference.Count == 1) && (foreignKeyProperties.Count == 0)) { var property = TryGetProperty(dependentEntityType, baseName + "Id", propertiesToReference.Single().ClrType.UnwrapNullableType()); if (property != null) { foreignKeyProperties.Add(property); } } if (foreignKeyProperties.Count < propertiesToReference.Count) { return(null); } if (!ForeignKey.AreCompatible( propertiesToReference, foreignKeyProperties, principalEntityType, dependentEntityType, shouldThrow: false)) { return(null); } var primaryKey = dependentEntityType.FindPrimaryKey(); if (primaryKey != null) { if (foreignKeyProperties.All(property => primaryKey.Properties.Contains(property))) { return(null); } } // Don't match with only Id since it is ambigious. PK in dependent entity used as FK is matched elsewhere if ((foreignKeyProperties.Count == 1) && (foreignKeyProperties.Single().Name == "Id")) { return(null); } return(foreignKeyProperties); }
private IReadOnlyList <Property> FindMatchingProperties( ForeignKey foreignKey, string baseName, bool onDependent, bool matchPK = false) { var dependentEntityType = onDependent ? foreignKey.DeclaringEntityType : foreignKey.PrincipalEntityType; var principalEntityType = onDependent ? foreignKey.PrincipalEntityType : foreignKey.DeclaringEntityType; var propertiesToReference = onDependent ? foreignKey.PrincipalKey.Properties : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties; if (propertiesToReference == null) { return(null); } var foreignKeyProperties = new Property[propertiesToReference.Count]; var matchFound = true; for (var i = 0; i < propertiesToReference.Count; i++) { var referencedProperty = propertiesToReference[i]; var property = TryGetProperty(dependentEntityType, baseName, referencedProperty.Name, referencedProperty.ClrType.UnwrapNullableType()); if (property == null) { matchFound = false; continue; } foreignKeyProperties[i] = property; } if (!matchFound && propertiesToReference.Count == 1) { var property = TryGetProperty(dependentEntityType, baseName, "Id", propertiesToReference.Single().ClrType.UnwrapNullableType()); if (property != null) { foreignKeyProperties[0] = property; matchFound = true; } } if (!matchFound) { return(null); } if (!ForeignKey.AreCompatible( propertiesToReference, foreignKeyProperties, principalEntityType, dependentEntityType, false)) { return(null); } foreach (var key in dependentEntityType.GetKeys()) { if (key.Properties.All(property => foreignKeyProperties.Contains(property)) && (!foreignKey.IsUnique || (key.IsPrimaryKey() && !matchPK))) { return(null); } } // Don't match with only Id since it is ambiguous. PK in dependent entity used as FK is matched elsewhere if (foreignKeyProperties.Length == 1 && foreignKeyProperties[0].Name == "Id") { return(null); } return(foreignKeyProperties); }
private IReadOnlyList <Property> FindMatchingProperties( ForeignKey foreignKey, string baseName, bool onDependent, bool matchPK = false) { var dependentEntityType = onDependent ? foreignKey.DeclaringEntityType : foreignKey.PrincipalEntityType; var principalEntityType = onDependent ? foreignKey.PrincipalEntityType : foreignKey.DeclaringEntityType; var propertiesToReference = onDependent ? foreignKey.PrincipalKey.Properties : foreignKey.DeclaringEntityType.FindPrimaryKey()?.Properties; if (propertiesToReference == null) { return(null); } var foreignKeyProperties = new Property[propertiesToReference.Count]; var matchFound = true; for (var i = 0; i < propertiesToReference.Count; i++) { var referencedProperty = propertiesToReference[i]; var property = TryGetProperty( dependentEntityType, baseName, referencedProperty.Name); if (property == null) { matchFound = false; continue; } foreignKeyProperties[i] = property; } if (!matchFound && propertiesToReference.Count == 1) { var property = TryGetProperty( dependentEntityType, baseName, "Id"); if (property != null) { foreignKeyProperties[0] = property; matchFound = true; } } if (!matchFound) { return(null); } if (!ForeignKey.AreCompatible( propertiesToReference, foreignKeyProperties, principalEntityType, dependentEntityType, false)) { _logger.IncompatibleMatchingForeignKeyProperties(foreignKeyProperties, propertiesToReference); return(new Property[0]); } foreach (var key in dependentEntityType.GetKeys()) { if (key.Properties.All(property => foreignKeyProperties.Contains(property)) && (!foreignKey.IsUnique || (key.IsPrimaryKey() && !matchPK))) { return(new Property[0]); } } return(foreignKeyProperties); }