protected virtual EntityType ResolveEntityType([NotNull] string entityTypeName) { if (DeclaringEntityType.Name == entityTypeName) { return((EntityType)DeclaringEntityType); } if (RelatedEntityType.Name == entityTypeName) { return((EntityType)RelatedEntityType); } if (DeclaringEntityType.DisplayName() == entityTypeName) { return((EntityType)DeclaringEntityType); } if (RelatedEntityType.DisplayName() == entityTypeName) { return((EntityType)RelatedEntityType); } if (DeclaringEntityType.HasSharedClrType && DeclaringEntityType.ShortName() == entityTypeName) { return((EntityType)DeclaringEntityType); } return(RelatedEntityType.HasSharedClrType && RelatedEntityType.ShortName() == entityTypeName ? (EntityType)RelatedEntityType : null); }
/// <summary> /// Configures the referential constraint for the navigation property. The dependent property will be added /// as non-nullable primitive property into the declaring entity type if it's not in the entity type. /// </summary> /// <param name="constraint">The dependent and principal property info pair.</param> public NavigationPropertyConfiguration HasConstraint(KeyValuePair <PropertyInfo, PropertyInfo> constraint) { if (constraint.Key == null) { throw Error.ArgumentNull("dependentPropertyInfo"); } if (constraint.Value == null) { throw Error.ArgumentNull("principalPropertyInfo"); } // OData V3 spec: The multiplicity of navigation property with referential constraint MUST be 1 or 0..1. if (Multiplicity == EdmMultiplicity.Many) { throw Error.NotSupported(SRResources.ReferentialConstraintOnManyNavigationPropertyNotSupported, Name, DeclaringEntityType.ClrType.FullName); } if (ValidateConstraint(constraint)) { return(this); } PrimitivePropertyConfiguration dependentConfiguration = DeclaringEntityType.AddProperty(constraint.Key); // Because principal properties and keys are required. So as dependent properties. dependentConfiguration.IsRequired(); _referentialConstraint.Add(constraint); return(this); }
/// <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 void UpdateConfigurationSource(ConfigurationSource configurationSource) { _configurationSource = _configurationSource.Max(configurationSource); DeclaringEntityType.UpdateConfigurationSource(configurationSource); PrincipalEntityType.UpdateConfigurationSource(configurationSource); }
public ForeignKey(Microsoft.EntityFrameworkCore.Metadata.IForeignKey foreignKey, EntityType entityType) { DeclaringEntityType = entityType.Model.FindEntityType(foreignKey.DeclaringEntityType.Name); Properties = foreignKey.Properties.Select(p => DeclaringEntityType.FindProperty(p.Name)).ToList(); PrincipalEntityType = entityType.Model.FindEntityType(foreignKey.PrincipalEntityType.Name); PrincipalKey = new Key(foreignKey.PrincipalKey, PrincipalEntityType); }
/// <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 void SetIsConcurrencyToken(bool concurrencyToken, ConfigurationSource configurationSource) { if (IsConcurrencyToken != concurrencyToken) { SetFlag(concurrencyToken, PropertyFlags.IsConcurrencyToken); DeclaringEntityType.PropertyMetadataChanged(); } UpdateIsConcurrencyTokenConfigurationSource(configurationSource); }
/// <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 void SetIsStoreGeneratedAlways(bool storeGeneratedAlways, ConfigurationSource configurationSource) { if (IsStoreGeneratedAlways != storeGeneratedAlways) { SetFlag(storeGeneratedAlways, PropertyFlags.StoreGeneratedAlways); DeclaringEntityType.PropertyMetadataChanged(); } UpdateIsStoreGeneratedAlwaysConfigurationSource(configurationSource); }
public virtual ForeignKey?SetForeignKey([CanBeNull] ForeignKey?foreignKey, ConfigurationSource configurationSource) { EnsureReadonly(false); var oldForeignKey = ForeignKey; var isChanging = foreignKey != ForeignKey; if (oldForeignKey != null) { oldForeignKey.ReferencingSkipNavigations !.Remove(this); } if (foreignKey == null) { ForeignKey = null; _foreignKeyConfigurationSource = null; return(isChanging ? (ForeignKey?)DeclaringEntityType.Model.ConventionDispatcher .OnSkipNavigationForeignKeyChanged(Builder, foreignKey, oldForeignKey) : foreignKey); } var expectedEntityType = IsOnDependent ? foreignKey.DeclaringEntityType : foreignKey.PrincipalEntityType; if (expectedEntityType != DeclaringEntityType) { var message = IsOnDependent ? CoreStrings.SkipNavigationForeignKeyWrongDependentType( foreignKey.Properties.Format(), DeclaringEntityType.DisplayName(), Name, expectedEntityType.DisplayName()) : CoreStrings.SkipNavigationForeignKeyWrongPrincipalType( foreignKey.Properties.Format(), DeclaringEntityType.DisplayName(), Name, expectedEntityType.DisplayName()); throw new InvalidOperationException(message); } ProcessForeignKey(foreignKey); UpdateForeignKeyConfigurationSource(configurationSource); if (Inverse?.JoinEntityType != null && Inverse.JoinEntityType != JoinEntityType) { throw new InvalidOperationException( CoreStrings.SkipInverseMismatchedForeignKey( foreignKey.Properties.Format(), Name, JoinEntityType !.DisplayName(), Inverse.Name, Inverse.JoinEntityType.DisplayName())); } return(isChanging ? (ForeignKey)DeclaringEntityType.Model.ConventionDispatcher .OnSkipNavigationForeignKeyChanged(Builder, foreignKey, oldForeignKey) : foreignKey); }
public virtual Navigation HasDependentToPrincipal( [CanBeNull] string name, // ReSharper disable once MethodOverloadWithOptionalParameter ConfigurationSource configurationSource = ConfigurationSource.Explicit, bool runConventions = true) { var oldNavigation = DependentToPrincipal; if (name == oldNavigation?.Name) { UpdateDependentToPrincipalConfigurationSource(configurationSource); return(oldNavigation); } if (oldNavigation != null) { Debug.Assert(oldNavigation.Name != null); DeclaringEntityType.RemoveNavigation(oldNavigation.Name); } Navigation navigation = null; if (name != null) { navigation = DeclaringEntityType.AddNavigation(name, this, pointsToPrincipal: true); } DependentToPrincipal = navigation; UpdateDependentToPrincipalConfigurationSource(configurationSource); if (runConventions) { if (oldNavigation != null) { Debug.Assert(oldNavigation.Name != null); DeclaringEntityType.Model.ConventionDispatcher.OnNavigationRemoved( DeclaringEntityType.Builder, PrincipalEntityType.Builder, oldNavigation.Name); } if (navigation != null) { navigation = DeclaringEntityType.Model.ConventionDispatcher.OnNavigationAdded(Builder, navigation) ?.Metadata.DependentToPrincipal; } } return(navigation ?? oldNavigation); }
/// <summary> /// Configures the referential constraint with the dependent and principal property pair. /// </summary> /// <param name="constraint">The dependent and principal property pair.</param> public NavigationPropertyConfiguration HasConstraint(KeyValuePair <PropertyInfo, PropertyInfo> constraint) { if (constraint.Key == null) { throw Error.ArgumentNull("dependentPropertyInfo"); } if (constraint.Value == null) { throw Error.ArgumentNull("principalPropertyInfo"); } if (Multiplicity == EdmMultiplicity.Many) { throw Error.NotSupported(SRResources.ReferentialConstraintOnManyNavigationPropertyNotSupported, Name, DeclaringEntityType.ClrType.FullName); } if (ValidateConstraint(constraint)) { return(this); } EntityTypeConfiguration principalEntity = DeclaringEntityType.ModelBuilder.StructuralTypes .OfType <EntityTypeConfiguration>().FirstOrDefault(e => e.ClrType == RelatedClrType); Contract.Assert(principalEntity != null); PrimitivePropertyConfiguration principal = principalEntity.AddProperty(constraint.Value); PrimitivePropertyConfiguration dependent = DeclaringEntityType.AddProperty(constraint.Key); // If the navigation property on which the referential constraint is defined or the principal property // is nullable, then the dependent property MUST be nullable. if (Multiplicity == EdmMultiplicity.ZeroOrOne || principal.OptionalProperty) { dependent.OptionalProperty = true; } // If both the navigation property and the principal property are not nullable, // then the dependent property MUST be marked with the Nullable="false" attribute value. if (Multiplicity == EdmMultiplicity.One && !principal.OptionalProperty) { dependent.OptionalProperty = false; } _referentialConstraint.Add(constraint); return(this); }
private static IReadOnlyList <string>?FindCandidateDependentPropertiesThroughNavigation( IConventionForeignKeyBuilder relationshipBuilder, bool pointsToPrincipal) { var navigation = pointsToPrincipal ? relationshipBuilder.Metadata.DependentToPrincipal : relationshipBuilder.Metadata.PrincipalToDependent !; var navigationFkAttribute = navigation != null ? GetForeignKeyAttribute(navigation) : null; if (navigationFkAttribute == null) { return(null); } var properties = navigationFkAttribute.Name.Split(',').Select(p => p.Trim()).ToList(); if (properties.Any(p => string.IsNullOrWhiteSpace(p) || p == navigation !.Name)) { throw new InvalidOperationException( CoreStrings.InvalidPropertyListOnNavigation( navigation !.Name, navigation.DeclaringEntityType.DisplayName(), navigationFkAttribute.Name)); } var navigationPropertyTargetType = navigation !.DeclaringEntityType.GetRuntimeProperties()[navigation.Name].PropertyType; var otherNavigations = navigation.DeclaringEntityType.GetRuntimeProperties().Values .Where(p => p.PropertyType == navigationPropertyTargetType && p.GetSimpleMemberName() != navigation.Name) .OrderBy(p => p.GetSimpleMemberName()); foreach (var propertyInfo in otherNavigations) { var attribute = GetAttribute <ForeignKeyAttribute>(propertyInfo); if (attribute?.Name == navigationFkAttribute.Name) { throw new InvalidOperationException( CoreStrings.MultipleNavigationsSameFk( navigation.DeclaringEntityType.DisplayName(), attribute.Name, $"'{navigation.Name}', '{propertyInfo.Name}'")); } } return(properties); }
/// <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 virtual EntityType ResolveEntityType([NotNull] string entityTypeName) { if (DeclaringEntityType.Name == entityTypeName) { return(DeclaringEntityType); } if (RelatedEntityType.Name == entityTypeName) { return(RelatedEntityType); } if (DeclaringEntityType.DisplayName() == entityTypeName) { return(DeclaringEntityType); } return(RelatedEntityType.DisplayName() == entityTypeName ? RelatedEntityType : null); }
public virtual Navigation HasDependentToPrincipal([CanBeNull] string name) { var oldNavigation = DependentToPrincipal; if (oldNavigation != null) { DeclaringEntityType.RemoveNavigation(oldNavigation.Name); } Navigation newNavigation = null; if (name != null) { newNavigation = DeclaringEntityType.AddNavigation(name, this, pointsToPrincipal: true); } DependentToPrincipal = newNavigation; return(newNavigation ?? oldNavigation); }
private InternalRelationshipBuilder HasForeignKeyBuilder( EntityType dependentEntityType, string dependentEntityTypeName, Func <InternalRelationshipBuilder, EntityType, InternalRelationshipBuilder> hasForeignKey) { if (dependentEntityType == null) { throw new InvalidOperationException(CoreStrings.DependentEntityTypeNotInRelationship( DeclaringEntityType.DisplayName(), RelatedEntityType.DisplayName(), dependentEntityTypeName)); } using (var batch = dependentEntityType.Model.ConventionDispatcher.StartBatch()) { var builder = Builder.RelatedEntityTypes( GetOtherEntityType(dependentEntityType), dependentEntityType, ConfigurationSource.Explicit); builder = hasForeignKey(builder, dependentEntityType); return(batch.Run(builder)); } }
private InternalForeignKeyBuilder HasPrincipalKeyBuilder( EntityType principalEntityType, string principalEntityTypeName, Func <InternalForeignKeyBuilder, InternalForeignKeyBuilder> hasPrincipalKey) { if (principalEntityType == null) { throw new InvalidOperationException( CoreStrings.PrincipalEntityTypeNotInRelationship( DeclaringEntityType.DisplayName(), RelatedEntityType.DisplayName(), principalEntityTypeName)); } using var batch = principalEntityType.Model.ConventionDispatcher.DelayConventions(); var builder = Builder.HasEntityTypes( principalEntityType, GetOtherEntityType(principalEntityType), ConfigurationSource.Explicit); builder = hasPrincipalKey(builder); return(batch.Run(builder)); }
public virtual void SetIsShadowProperty(bool shadowProperty, ConfigurationSource configurationSource) { if (IsShadowProperty != shadowProperty) { if (shadowProperty == false) { if (DeclaringEntityType.ClrType == null) { throw new InvalidOperationException(CoreStrings.ClrPropertyOnShadowEntity(Name, DeclaringEntityType.DisplayName())); } var clrProperty = DeclaringEntityType.ClrType.GetPropertiesInHierarchy(Name).FirstOrDefault(); if (clrProperty == null) { throw new InvalidOperationException(CoreStrings.NoClrProperty(Name, DeclaringEntityType.DisplayName())); } if (ClrType == null) { ClrType = clrProperty.PropertyType; } else if (ClrType != clrProperty.PropertyType) { throw new InvalidOperationException(CoreStrings.PropertyWrongClrType(Name, DeclaringEntityType.DisplayName())); } } SetFlag(shadowProperty, PropertyFlags.IsShadowProperty); DeclaringEntityType.PropertyMetadataChanged(); } else { SetFlag(shadowProperty, PropertyFlags.IsShadowProperty); } UpdateIsShadowPropertyConfigurationSource(configurationSource); }
/// <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 void SetProperties( IReadOnlyList <Property> properties, Key principalKey, ConfigurationSource?configurationSource) { Validate(properties, principalKey, DeclaringEntityType, PrincipalEntityType); var oldProperties = Properties; var oldPrincipalKey = PrincipalKey; DeclaringEntityType.OnForeignKeyUpdating(this); Properties = properties; PrincipalKey = principalKey; DeclaringEntityType.OnForeignKeyUpdated(this); if (configurationSource != null) { UpdatePropertiesConfigurationSource(configurationSource.Value); UpdatePrincipalKeyConfigurationSource(configurationSource.Value); } DeclaringEntityType.Model.ConventionDispatcher.OnForeignKeyPropertiesChanged(Builder, oldProperties, oldPrincipalKey); }
/// <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> private Navigation Navigation( PropertyIdentity?propertyIdentity, ConfigurationSource configurationSource, bool runConventions, bool pointsToPrincipal) { var name = propertyIdentity?.Name; var oldNavigation = pointsToPrincipal ? DependentToPrincipal : PrincipalToDependent; if (name == oldNavigation?.Name) { if (pointsToPrincipal) { UpdateDependentToPrincipalConfigurationSource(configurationSource); } else { UpdatePrincipalToDependentConfigurationSource(configurationSource); } return(oldNavigation); } if (oldNavigation != null) { Debug.Assert(oldNavigation.Name != null); if (pointsToPrincipal) { DeclaringEntityType.RemoveNavigation(oldNavigation.Name); } else { PrincipalEntityType.RemoveNavigation(oldNavigation.Name); } } Navigation navigation = null; var property = propertyIdentity?.Property; if (property != null) { navigation = pointsToPrincipal ? DeclaringEntityType.AddNavigation(property, this, pointsToPrincipal: true) : PrincipalEntityType.AddNavigation(property, this, pointsToPrincipal: false); } else if (name != null) { navigation = pointsToPrincipal ? DeclaringEntityType.AddNavigation(name, this, pointsToPrincipal: true) : PrincipalEntityType.AddNavigation(name, this, pointsToPrincipal: false); } if (pointsToPrincipal) { DependentToPrincipal = navigation; UpdateDependentToPrincipalConfigurationSource(configurationSource); } else { PrincipalToDependent = navigation; UpdatePrincipalToDependentConfigurationSource(configurationSource); } if (runConventions) { if (oldNavigation != null) { Debug.Assert(oldNavigation.Name != null); if (pointsToPrincipal) { DeclaringEntityType.Model.ConventionDispatcher.OnNavigationRemoved( DeclaringEntityType.Builder, PrincipalEntityType.Builder, oldNavigation.Name, oldNavigation.PropertyInfo); } else { DeclaringEntityType.Model.ConventionDispatcher.OnNavigationRemoved( PrincipalEntityType.Builder, DeclaringEntityType.Builder, oldNavigation.Name, oldNavigation.PropertyInfo); } } if (navigation != null) { var builder = DeclaringEntityType.Model.ConventionDispatcher.OnNavigationAdded(Builder, navigation); navigation = pointsToPrincipal ? builder?.Metadata.DependentToPrincipal : builder?.Metadata.PrincipalToDependent; } } return(navigation ?? oldNavigation); }
/// <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> private Navigation Navigation( PropertyIdentity?propertyIdentity, ConfigurationSource configurationSource, bool pointsToPrincipal) { var name = propertyIdentity?.Name; if (pointsToPrincipal && PrincipalEntityType.IsKeyless) { throw new InvalidOperationException( CoreStrings.NavigationToKeylessType(name, PrincipalEntityType.DisplayName())); } if (!pointsToPrincipal && DeclaringEntityType.IsKeyless) { throw new InvalidOperationException( CoreStrings.NavigationToKeylessType(name, DeclaringEntityType.DisplayName())); } var oldNavigation = pointsToPrincipal ? DependentToPrincipal : PrincipalToDependent; if (name == oldNavigation?.Name) { if (pointsToPrincipal) { UpdateDependentToPrincipalConfigurationSource(configurationSource); } else { UpdatePrincipalToDependentConfigurationSource(configurationSource); } return(oldNavigation); } if (oldNavigation != null) { Debug.Assert(oldNavigation.Name != null); if (pointsToPrincipal) { DeclaringEntityType.RemoveNavigation(oldNavigation.Name); } else { PrincipalEntityType.RemoveNavigation(oldNavigation.Name); } } Navigation navigation = null; var property = propertyIdentity?.Property; if (property != null) { navigation = pointsToPrincipal ? DeclaringEntityType.AddNavigation(property, this, pointsToPrincipal: true) : PrincipalEntityType.AddNavigation(property, this, pointsToPrincipal: false); } else if (name != null) { navigation = pointsToPrincipal ? DeclaringEntityType.AddNavigation(name, this, pointsToPrincipal: true) : PrincipalEntityType.AddNavigation(name, this, pointsToPrincipal: false); } if (pointsToPrincipal) { DependentToPrincipal = navigation; UpdateDependentToPrincipalConfigurationSource(configurationSource); } else { PrincipalToDependent = navigation; UpdatePrincipalToDependentConfigurationSource(configurationSource); } if (oldNavigation != null) { Debug.Assert(oldNavigation.Name != null); if (pointsToPrincipal) { DeclaringEntityType.Model.ConventionDispatcher.OnNavigationRemoved( DeclaringEntityType.Builder, PrincipalEntityType.Builder, oldNavigation.Name, oldNavigation.GetIdentifyingMemberInfo()); } else { DeclaringEntityType.Model.ConventionDispatcher.OnNavigationRemoved( PrincipalEntityType.Builder, DeclaringEntityType.Builder, oldNavigation.Name, oldNavigation.GetIdentifyingMemberInfo()); } } if (navigation != null) { var builder = DeclaringEntityType.Model.ConventionDispatcher.OnNavigationAdded(Builder, navigation); navigation = pointsToPrincipal ? builder?.Metadata.DependentToPrincipal : builder?.Metadata.PrincipalToDependent; } return(navigation ?? oldNavigation); }
public virtual bool IsInUse() => DeclaringEntityType.FindForeignKeysInHierarchy(Properties).Any();
/// <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 override string ToString() // Interpolation okay; strings/debug output => $"'{DeclaringEntityType.DisplayName()}' {Property.Format(Properties)} -> '{PrincipalEntityType.DisplayName()}' {Property.Format(PrincipalKey.Properties)}";
private PropertyIndexes CalculateIndexes() => DeclaringEntityType.CalculateIndexes(this);
/// <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 void SetIsReadOnlyAfterSave(bool readOnlyAfterSave, ConfigurationSource configurationSource) { if (!readOnlyAfterSave && Keys != null) { throw new InvalidOperationException(CoreStrings.KeyPropertyMustBeReadOnly(Name, DeclaringEntityType.DisplayName())); } SetFlag(readOnlyAfterSave, PropertyFlags.IsReadOnlyAfterSave); UpdateIsReadOnlyAfterSaveConfigurationSource(configurationSource); }
/// <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 void SetIsNullable(bool nullable, ConfigurationSource configurationSource) { if (nullable) { if (!ClrType.IsNullableType()) { throw new InvalidOperationException(CoreStrings.CannotBeNullable(Name, DeclaringEntityType.DisplayName(), ClrType.ShortDisplayName())); } if (Keys != null) { throw new InvalidOperationException(CoreStrings.CannotBeNullablePK(Name, DeclaringEntityType.DisplayName())); } } UpdateIsNullableConfigurationSource(configurationSource); var isChanging = IsNullable != nullable; SetFlag(nullable, PropertyFlags.IsNullable); if (isChanging) { DeclaringEntityType.Model.ConventionDispatcher.OnPropertyNullableChanged(Builder); } }
/// <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 override string ToString() => $"'{DeclaringEntityType.DisplayName()}' {Property.Format(Properties)} -> '{PrincipalEntityType.DisplayName()}' {Property.Format(PrincipalKey.Properties)}";