Example #1
0
        /// <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}.");
                }
            }