public override IConventionAnnotation?OnNavigationAnnotationChanged( IConventionForeignKeyBuilder relationshipBuilder, IConventionNavigation navigation, string name, IConventionAnnotation?annotation, IConventionAnnotation?oldAnnotation) { if (!relationshipBuilder.Metadata.IsInModel || relationshipBuilder.Metadata.GetNavigation(navigation.IsOnDependent) != navigation) { return(null); } using (_dispatcher.DelayConventions()) { _annotationConventionContext.ResetState(annotation); foreach (var navigationConvention in _conventionSet.NavigationAnnotationChangedConventions) { navigationConvention.ProcessNavigationAnnotationChanged( relationshipBuilder, navigation, name, annotation, oldAnnotation, _annotationConventionContext); if (_annotationConventionContext.ShouldStopProcessing()) { return(_annotationConventionContext.Result); } } } return(annotation); }
/// <summary> /// Called after a navigation property that has an attribute is added to an entity type. /// </summary> /// <param name="relationshipBuilder"> The builder for the relationship. </param> /// <param name="navigation"> The navigation. </param> /// <param name="attribute"> The attribute. </param> /// <param name="context"> Additional information associated with convention execution. </param> public override void ProcessNavigationAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionNavigation navigation, InversePropertyAttribute attribute, IConventionContext <IConventionNavigation> context) { if (relationshipBuilder.Metadata.DeclaringEntityType.HasDefiningNavigation() || relationshipBuilder.Metadata.DeclaringEntityType.IsOwned() || relationshipBuilder.Metadata.PrincipalEntityType.HasDefiningNavigation() || relationshipBuilder.Metadata.PrincipalEntityType.IsOwned()) { return; } var newRelationship = ConfigureInverseNavigation( navigation.DeclaringEntityType.Builder, navigation.GetIdentifyingMemberInfo(), navigation.GetTargetType().Builder, attribute); if (newRelationship != relationshipBuilder) { if (newRelationship == null) { context.StopProcessingIfChanged(null); return; } var newNavigation = navigation.IsDependentToPrincipal() ? newRelationship.Metadata.DependentToPrincipal : newRelationship.Metadata.PrincipalToDependent; context.StopProcessingIfChanged(newNavigation); } }
/// <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 bool CanSetAutoInclude(bool?autoInclude, ConfigurationSource configurationSource) { IConventionNavigation conventionNavigation = Metadata; return(configurationSource.Overrides(conventionNavigation.GetIsEagerLoadedConfigurationSource()) || conventionNavigation.IsEagerLoaded == autoInclude); }
/// <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 bool CanSetIsEagerLoaded(bool?eagerLoaded, ConfigurationSource configurationSource) { IConventionNavigation conventionNavigation = Metadata; return(configurationSource.Overrides(conventionNavigation.GetIsEagerLoadedConfigurationSource()) || conventionNavigation.IsEagerLoaded == eagerLoaded); }
public void Can_only_override_lower_or_equal_source_PropertyAccessMode() { var builder = CreateInternalNavigationBuilder(); IConventionNavigation metadata = builder.Metadata; Assert.Equal(PropertyAccessMode.PreferField, metadata.GetPropertyAccessMode()); Assert.Null(metadata.GetPropertyAccessModeConfigurationSource()); Assert.True(builder.CanSetPropertyAccessMode(PropertyAccessMode.PreferProperty, ConfigurationSource.DataAnnotation)); Assert.NotNull(builder.UsePropertyAccessMode(PropertyAccessMode.PreferProperty, ConfigurationSource.DataAnnotation)); Assert.Equal(PropertyAccessMode.PreferProperty, metadata.GetPropertyAccessMode()); Assert.Equal(ConfigurationSource.DataAnnotation, metadata.GetPropertyAccessModeConfigurationSource()); Assert.True(builder.CanSetPropertyAccessMode(PropertyAccessMode.PreferProperty, ConfigurationSource.Convention)); Assert.False(builder.CanSetPropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction, ConfigurationSource.Convention)); Assert.NotNull(builder.UsePropertyAccessMode(PropertyAccessMode.PreferProperty, ConfigurationSource.Convention)); Assert.Null(builder.UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction, ConfigurationSource.Convention)); Assert.Equal(PropertyAccessMode.PreferProperty, metadata.GetPropertyAccessMode()); Assert.Equal(ConfigurationSource.DataAnnotation, metadata.GetPropertyAccessModeConfigurationSource()); Assert.True(builder.CanSetPropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction, ConfigurationSource.DataAnnotation)); Assert.NotNull(builder.UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction, ConfigurationSource.DataAnnotation)); Assert.Equal(PropertyAccessMode.PreferFieldDuringConstruction, metadata.GetPropertyAccessMode()); Assert.Equal(ConfigurationSource.DataAnnotation, metadata.GetPropertyAccessModeConfigurationSource()); Assert.True(builder.CanSetPropertyAccessMode(null, ConfigurationSource.DataAnnotation)); Assert.NotNull(builder.UsePropertyAccessMode(null, ConfigurationSource.DataAnnotation)); Assert.Equal(PropertyAccessMode.PreferField, metadata.GetPropertyAccessMode()); Assert.Null(metadata.GetPropertyAccessModeConfigurationSource()); }
public override IConventionNavigation OnNavigationAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionNavigation navigation) { if (relationshipBuilder.Metadata.Builder == null || relationshipBuilder.Metadata.GetNavigation(navigation.IsDependentToPrincipal()) != navigation) { return(null); } using (_dispatcher.DelayConventions()) { _navigationConventionContext.ResetState(navigation); foreach (var navigationConvention in _conventionSet.NavigationAddedConventions) { navigationConvention.ProcessNavigationAdded(relationshipBuilder, navigation, _navigationConventionContext); if (_navigationConventionContext.ShouldStopProcessing()) { return(_navigationConventionContext.Result); } } } if (relationshipBuilder.Metadata.GetNavigation(navigation.IsDependentToPrincipal()) != navigation) { return(null); } return(navigation); }
public void Can_only_override_lower_or_equal_source_IsEagerLoaded() { var builder = CreateInternalNavigationBuilder(); IConventionNavigation metadata = builder.Metadata; Assert.False(metadata.IsEagerLoaded); Assert.Null(metadata.GetIsEagerLoadedConfigurationSource()); Assert.True(builder.CanSetAutoInclude(autoInclude: true, ConfigurationSource.DataAnnotation)); Assert.NotNull(builder.AutoInclude(autoInclude: true, ConfigurationSource.DataAnnotation)); Assert.True(metadata.IsEagerLoaded); Assert.Equal(ConfigurationSource.DataAnnotation, metadata.GetIsEagerLoadedConfigurationSource()); Assert.True(builder.CanSetAutoInclude(autoInclude: true, ConfigurationSource.Convention)); Assert.False(builder.CanSetAutoInclude(autoInclude: false, ConfigurationSource.Convention)); Assert.NotNull(builder.AutoInclude(autoInclude: true, ConfigurationSource.Convention)); Assert.Null(builder.AutoInclude(autoInclude: false, ConfigurationSource.Convention)); Assert.True(metadata.IsEagerLoaded); Assert.Equal(ConfigurationSource.DataAnnotation, metadata.GetIsEagerLoadedConfigurationSource()); Assert.True(builder.CanSetAutoInclude(autoInclude: false, ConfigurationSource.DataAnnotation)); Assert.NotNull(builder.AutoInclude(autoInclude: false, ConfigurationSource.DataAnnotation)); Assert.False(metadata.IsEagerLoaded); Assert.Equal(ConfigurationSource.DataAnnotation, metadata.GetIsEagerLoadedConfigurationSource()); Assert.True(builder.CanSetAutoInclude(null, ConfigurationSource.DataAnnotation)); Assert.NotNull(builder.AutoInclude(null, ConfigurationSource.DataAnnotation)); Assert.False(metadata.IsEagerLoaded); Assert.Null(metadata.GetIsEagerLoadedConfigurationSource()); }
/// <summary> /// Sets a value indicating whether this navigation should be eager loaded by default. /// </summary> /// <param name="navigation"> The navigation property to set whether it should be eager loaded for. </param>. /// <param name="eagerLoaded"> A value indicating whether this navigation should be eager loaded by default. </param> /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param> public static void IsEagerLoaded( [NotNull] this IConventionNavigation navigation, bool?eagerLoaded, bool fromDataAnnotation = false) { Check.NotNull(navigation, nameof(navigation)); navigation.SetAnnotation(CoreAnnotationNames.EagerLoaded, eagerLoaded, fromDataAnnotation); }
/// <summary> /// Called after a navigation is added to the entity type. /// </summary> /// <param name="relationshipBuilder"> The builder for the foreign key. </param> /// <param name="navigation"> The navigation. </param> /// <param name="context"> Additional information associated with convention execution. </param> public virtual void ProcessNavigationAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionNavigation navigation, IConventionContext <IConventionNavigation> context) { var newRelationshipBuilder = DiscoverProperties(relationshipBuilder, context); context.StopProcessingIfChanged(newRelationshipBuilder?.Metadata.GetNavigation(navigation.IsDependentToPrincipal())); }
public override IConventionAnnotation?OnNavigationAnnotationChanged( IConventionForeignKeyBuilder relationshipBuilder, IConventionNavigation navigation, string name, IConventionAnnotation?annotation, IConventionAnnotation?oldAnnotation) { Add(new OnNavigationAnnotationChangedNode(relationshipBuilder, navigation, name, annotation, oldAnnotation)); return(annotation); }
private static bool CanMergeWith( IConventionNavigation existingNavigation, MemberInfo inverse, IConventionEntityTypeBuilder inverseEntityTypeBuilder) { var fk = existingNavigation.ForeignKey; return((fk.IsSelfReferencing() || fk.GetRelatedEntityType(existingNavigation.DeclaringEntityType) == inverseEntityTypeBuilder.Metadata) && fk.Builder.CanSetNavigation(inverse, !existingNavigation.IsOnDependent)); }
/// <summary> /// Called after a navigation is added to the entity type. /// </summary> /// <param name="relationshipBuilder"> The builder for the foreign key. </param> /// <param name="navigation"> The navigation. </param> /// <param name="context"> Additional information associated with convention execution. </param> public virtual void ProcessNavigationAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionNavigation navigation, IConventionContext <IConventionNavigation> context) { var field = GetFieldToSet(navigation); if (field != null) { relationshipBuilder.HasField(field, navigation.IsDependentToPrincipal()); } }
/// <summary> /// Loads the data navigation property and sets it in the entity. /// </summary> /// <param name="entityEntry">The entity entry from the context.</param> /// <param name="navigation">The navigation property.</param> protected virtual void LoadNavigationProperty(EntityEntry entityEntry, IConventionNavigation navigation) { if (navigation.ForeignKey.DeclaringEntityType != navigation.DeclaringEntityType) { // inverse property return; } var keyProperty = navigation.ForeignKey.Properties[0]; var idValue = entityEntry.Property(keyProperty.Name).CurrentValue; Guid id = (idValue as Guid?) ?? Guid.Empty; if (id != Guid.Empty) { var getter = navigation.GetGetter(); var currentValue = getter.GetClrValue(entityEntry.Entity); if (currentValue is IIdentifiable identifiable && identifiable.Id == id) { // loaded already return; } IRepository?repository = null; try { repository = this.RepositoryManager.GetRepository(navigation.TargetEntityType.ClrType); } catch (RepositoryNotFoundException ex) { this.logger.LogError(ex, $"Repository not found: {ex.Message}"); } if (repository != null) { #pragma warning disable EF1001 // Internal EF Core API usage. if (navigation is Navigation { Setter : { } } concreteNavigation) { concreteNavigation.Setter.SetClrValue(entityEntry.Entity, repository.GetById(id)); } else { this.logger.LogError($"Could not find setter for navigation {navigation}"); } #pragma warning restore EF1001 // Internal EF Core API usage. } else { this.logger.LogError($"Repository not found for navigation target type {navigation.TargetEntityType}."); } }
/// <summary> /// Called after a navigation is added to the entity type. /// </summary> /// <param name="relationshipBuilder"> The builder for the foreign key. </param> /// <param name="navigation"> The navigation. </param> /// <param name="context"> Additional information associated with convention execution. </param> public virtual void ProcessNavigationAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionNavigation navigation, IConventionContext <IConventionNavigation> context) { Check.NotNull(relationshipBuilder, nameof(relationshipBuilder)); Check.NotNull(navigation, nameof(navigation)); var modelBuilder = relationshipBuilder.ModelBuilder; if (!IsNonNullable(modelBuilder, navigation) || navigation.IsCollection()) { return; } if (!navigation.IsDependentToPrincipal()) { var inverse = navigation.FindInverse(); if (inverse != null) { if (IsNonNullable(modelBuilder, inverse)) { Dependencies.Logger.NonNullableReferenceOnBothNavigations(navigation, inverse); return; } } if (!navigation.ForeignKey.IsUnique || relationshipBuilder.Metadata.GetPrincipalEndConfigurationSource() != null) { Dependencies.Logger.NonNullableReferenceOnDependent(navigation.ForeignKey.PrincipalToDependent); return; } var newRelationshipBuilder = relationshipBuilder.HasEntityTypes( relationshipBuilder.Metadata.DeclaringEntityType, relationshipBuilder.Metadata.PrincipalEntityType); if (newRelationshipBuilder == null) { return; } Dependencies.Logger.NonNullableInverted(newRelationshipBuilder.Metadata.DependentToPrincipal); relationshipBuilder = newRelationshipBuilder; } relationshipBuilder.IsRequired(true); context.StopProcessingIfChanged(relationshipBuilder.Metadata.DependentToPrincipal); }
/// <summary> /// Called after a navigation property that has an attribute is added to an entity type. /// </summary> /// <param name="relationshipBuilder"> The builder for the relationship. </param> /// <param name="navigation"> The navigation. </param> /// <param name="attribute"> The attribute. </param> /// <param name="context"> Additional information associated with convention execution. </param> public override void ProcessNavigationAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionNavigation navigation, RequiredAttribute attribute, IConventionContext <IConventionNavigation> context) { Check.NotNull(relationshipBuilder, nameof(relationshipBuilder)); Check.NotNull(navigation, nameof(navigation)); Check.NotNull(attribute, nameof(attribute)); if (navigation.IsCollection) { Dependencies.Logger.RequiredAttributeOnCollection(navigation.ForeignKey.DependentToPrincipal); return; } if (!navigation.IsOnDependent) { var inverse = navigation.Inverse; if (inverse != null) { var attributes = GetAttributes <RequiredAttribute>(inverse.DeclaringEntityType, inverse); if (attributes.Any()) { Dependencies.Logger.RequiredAttributeOnBothNavigations(navigation, inverse); return; } } if (relationshipBuilder.Metadata.GetPrincipalEndConfigurationSource() != null) { Dependencies.Logger.RequiredAttributeOnDependent(navigation.ForeignKey.PrincipalToDependent); return; } var newRelationshipBuilder = relationshipBuilder.HasEntityTypes( relationshipBuilder.Metadata.DeclaringEntityType, relationshipBuilder.Metadata.PrincipalEntityType); if (newRelationshipBuilder == null) { return; } Dependencies.Logger.RequiredAttributeInverted(newRelationshipBuilder.Metadata.DependentToPrincipal); relationshipBuilder = newRelationshipBuilder; } relationshipBuilder.IsRequired(true, fromDataAnnotation: true); context.StopProcessingIfChanged(relationshipBuilder.Metadata.DependentToPrincipal); }
public OnNavigationAnnotationChangedNode( IConventionForeignKeyBuilder relationshipBuilder, IConventionNavigation navigation, string name, IConventionAnnotation?annotation, IConventionAnnotation?oldAnnotation) { RelationshipBuilder = relationshipBuilder; Navigation = navigation; Name = name; Annotation = annotation; OldAnnotation = oldAnnotation; }
/// <summary> /// Returns the attributes applied to the given navigation. /// </summary> /// <param name="entityType"> The entity type. </param> /// <param name="navigation"> The navigation. </param> /// <typeparam name="TCustomAttribute"> The attribute type to look for. </typeparam> /// <returns> The attributes applied to the given navigation. </returns> protected static IEnumerable <TCustomAttribute> GetAttributes <TCustomAttribute>( [NotNull] IConventionEntityType entityType, [NotNull] IConventionNavigation navigation) where TCustomAttribute : Attribute { var memberInfo = navigation.GetIdentifyingMemberInfo(); if (!entityType.HasClrType() || memberInfo == null) { return(Enumerable.Empty <TCustomAttribute>()); } return(Attribute.IsDefined(memberInfo, typeof(TCustomAttribute), inherit: true) ? memberInfo.GetCustomAttributes <TCustomAttribute>(true) : Enumerable.Empty <TCustomAttribute>()); }
/// <summary> /// Loads the navigation collection. /// </summary> /// <param name="entityEntry">The entity entry.</param> /// <param name="navigation">The navigation.</param> /// <param name="context">The context.</param> protected virtual void LoadCollection(EntityEntry entityEntry, IConventionNavigation navigation, DbContext context) { var foreignKeyProperty = navigation.ForeignKey.Properties[0]; var loadStatusAware = navigation.GetGetter().GetClrValue(entityEntry.Entity) as ILoadingStatusAwareList; if (loadStatusAware?.LoadingStatus == LoadingStatus.Loaded || loadStatusAware?.LoadingStatus == LoadingStatus.Loading) { // already loaded or loading return; } if (loadStatusAware is null && navigation.GetGetter().GetClrValue(entityEntry.Entity) != null) { // already loaded or loading return; } if (loadStatusAware is null) { throw new InvalidOperationException($"The collection is not implementing {nameof(ILoadingStatusAware)}"); } loadStatusAware.LoadingStatus = LoadingStatus.Loading; if (this.RepositoryManager.GetRepository(foreignKeyProperty.DeclaringEntityType.ClrType) is ILoadByProperty repository) { var foreignKeyValue = entityEntry.Property(navigation.ForeignKey.PrincipalKey.Properties[0].Name).CurrentValue; var items = repository.LoadByProperty(foreignKeyProperty, foreignKeyValue); foreach (var obj in items) { if (!loadStatusAware.Contains(obj)) { loadStatusAware.Add(obj); } } loadStatusAware.LoadingStatus = LoadingStatus.Loaded; } else { this.logger.LogWarning($"No repository found which supports loading by foreign key for type ${foreignKeyProperty.DeclaringEntityType.ClrType}."); loadStatusAware.LoadingStatus = LoadingStatus.Failed; } }
/// <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 IConventionAnnotation?OnNavigationAnnotationChanged( IConventionForeignKeyBuilder relationshipBuilder, IConventionNavigation navigation, string name, IConventionAnnotation?annotation, IConventionAnnotation?oldAnnotation) { if (CoreAnnotationNames.AllNames.Contains(name)) { return(annotation); } return(_scope.OnNavigationAnnotationChanged( relationshipBuilder, navigation, name, annotation, oldAnnotation)); }
/// <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 IConventionAnnotation OnNavigationAnnotationChanged( [NotNull] IConventionForeignKeyBuilder relationshipBuilder, [NotNull] IConventionNavigation navigation, [NotNull] string name, [CanBeNull] IConventionAnnotation annotation, [CanBeNull] IConventionAnnotation oldAnnotation) { if (CoreAnnotationNames.AllNames.Contains(name)) { return(annotation); } return(_scope.OnNavigationAnnotationChanged( relationshipBuilder, navigation, name, annotation, oldAnnotation)); }
/// <summary> /// Called after a navigation is added to the entity type. /// </summary> /// <param name="relationshipBuilder"> The builder for the foreign key. </param> /// <param name="navigation"> The navigation. </param> /// <param name="context"> Additional information associated with convention execution. </param> public virtual void ProcessNavigationAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionNavigation navigation, IConventionContext <IConventionNavigation> context) { Check.NotNull(relationshipBuilder, nameof(relationshipBuilder)); Check.NotNull(navigation, nameof(navigation)); var attributes = GetAttributes <TAttribute>(navigation.DeclaringEntityType, navigation); foreach (var attribute in attributes) { ProcessNavigationAdded(relationshipBuilder, navigation, attribute, context); if (((IReadableConventionContext)context).ShouldStopProcessing()) { break; } } }
private void ProcessNavigation(IConventionNavigation navigation) { var naviType = navigation.ClrType; if (ValueObjectMetadataLookup.Find(naviType) is null) { return; } var property = navigation.DeclaringEntityType.Builder .Property(naviType, navigation.Name)? .Metadata; if (property is null) { return; } SetConverterAndExecuteCallback(property); }
private bool IsNonNullable(IConventionModelBuilder modelBuilder, IConventionNavigation navigation) => navigation.DeclaringEntityType.HasClrType() && navigation.DeclaringEntityType.GetRuntimeProperties().Find(navigation.Name) is PropertyInfo propertyInfo &&
/// <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 IConventionNavigation OnNavigationAdded( [NotNull] IConventionRelationshipBuilder relationshipBuilder, [NotNull] IConventionNavigation navigation) => _scope.OnNavigationAdded(relationshipBuilder, navigation);
public abstract IConventionAnnotation OnNavigationAnnotationChanged( [NotNull] IConventionRelationshipBuilder relationshipBuilder, [NotNull] IConventionNavigation navigation, [NotNull] string name, [CanBeNull] IConventionAnnotation annotation, [CanBeNull] IConventionAnnotation oldAnnotation);
public abstract IConventionNavigation OnNavigationAdded( [NotNull] IConventionRelationshipBuilder relationshipBuilder, [NotNull] IConventionNavigation navigation);
private static InversePropertyAttribute GetInversePropertyAttribute(IConventionNavigation navigation) => GetAttribute <InversePropertyAttribute>(navigation.PropertyInfo);
private static ForeignKeyAttribute GetForeignKeyAttribute(IConventionNavigation navigation) => GetAttribute <ForeignKeyAttribute>(navigation.PropertyInfo);
/// <summary> /// Sets a value indicating whether this navigation should be eager loaded by default. /// </summary> /// <param name="navigation"> The navigation property to set whether it should be eager loaded. </param> /// <param name="eagerLoaded"> A value indicating whether this navigation should be eager loaded by default. </param> /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param> public static void SetIsEagerLoaded( [NotNull] this IConventionNavigation navigation, bool?eagerLoaded, bool fromDataAnnotation = false) => navigation.AsNavigation().SetIsEagerLoaded( eagerLoaded, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention);
/// <summary> /// Returns the configuration source for <see cref="NavigationExtensions.IsEagerLoaded" />. /// </summary> /// <param name="navigation"> The navigation property to find configuration source for. </param> /// <returns> The configuration source for <see cref="NavigationExtensions.IsEagerLoaded" />. </returns> public static ConfigurationSource?GetIsEagerLoadedConfigurationSource([NotNull] this IConventionNavigation navigation) => navigation.FindAnnotation(CoreAnnotationNames.EagerLoaded)?.GetConfigurationSource();