/// <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> /// 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}."); } }