/// <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, INavigation navigation, DbContext context) { var foreignKeyProperty = navigation.ForeignKey.Properties.First(); 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 == null && navigation.GetGetter().GetClrValue(entityEntry.Entity) != null) { // already loaded or loading return; } if (loadStatusAware == 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.First().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 { Log.Warn($"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, INavigation navigation) { if (navigation.ForeignKey.DeclaringEntityType != navigation.DeclaringEntityType) { // inverse property return; } var keyProperty = navigation.ForeignKey.Properties.First(); 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) && (currentValue as IIdentifiable).Id == id) { // loaded already return; } IRepository repository = null; try { repository = this.RepositoryManager.GetRepository(navigation.GetTargetType().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 concreteNavigation && concreteNavigation.Setter != null) { 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.GetTargetType()}."); } }
private static void FixupNavigation(INavigation navigation, object entity, object cached) { var value = navigation.GetGetter().GetClrValue(entity); if (value == null) { return; } if (navigation.FieldInfo != null) { navigation.FieldInfo.SetValue(cached, value); } else { navigation.GetSetter().SetClrValue(cached, value); } var inverse = navigation.FindInverse(); if (inverse == null) { return; } if (inverse.IsCollection()) { var collection = inverse.GetCollectionAccessor(); collection.Add(value, cached); } else { var setter = inverse.GetSetter(); if (value is IEnumerable enumerable) { foreach (var item in enumerable) { setter.SetClrValue(item, cached); } } else { setter.SetClrValue(value, cached); } } }
void InitializeKeyGetters() { _keyGetters = new List <IKeyGetter>(); HashSet <Property> visited = new HashSet <Property>(); foreach (Property property in _key.Properties) { if (property.IsForeignKey()) { if (!visited.Contains(property)) { IEnumerable <ForeignKey> foreignKeys = property.GetContainingForeignKeys(); if (foreignKeys.Count() != 1) { throw new Exception("not supported"); } ForeignKey foreignKey = foreignKeys.First(); foreach (Property prop in foreignKey.Properties) { visited.Add(prop); } INavigation navigation = foreignKey.GetNavigations() .Where(n => n.DeclaringEntityType.ClrType == _entityType.ClrType) .Single(); IEntityType fkType = navigation.GetTargetType(); IKey fkKey = fkType.FindPrimaryKey(); List <IClrPropertyGetter> fkKeyGetters = new List <IClrPropertyGetter>(); foreach (Property fkKeyProperty in fkKey.Properties) { fkKeyGetters.Add(fkKeyProperty.GetGetter()); _keySize++; } _keyGetters.Add(new ForeignKeyGetter(navigation.GetGetter(), fkKeyGetters)); } } else { visited.Add(property); _keyGetters.Add(new SimpleKeyGetter(property.GetGetter())); _keySize++; } } }
/// <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, INavigation navigation) { if (navigation.ForeignKey.DeclaringEntityType != navigation.DeclaringEntityType) { // inverse property return; } var keyProperty = navigation.ForeignKey.Properties.First(); 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) && (currentValue as IIdentifiable).Id == id) { // loaded already return; } IRepository repository = null; try { repository = this.contextProvider.RepositoryManager.GetRepository(navigation.GetTargetType().ClrType); } catch (RepositoryNotFoundException ex) { Log.Error($"Repository not found: {ex.Message}"); } if (repository != null) { var setter = navigation.GetSetter(); setter.SetClrValue(entityEntry.Entity, repository.GetById(id)); } else { Log.Error($"Repository not found for navigation target type {navigation.GetTargetType()}."); } } }
private static object TryFindPrincipal(IStateManager stateManager, INavigation navigation, object dependentEntity) { if (navigation.IsDependentToPrincipal()) { return navigation.GetGetter().GetClrValue(dependentEntity); } // TODO: Perf foreach (var principalEntry in stateManager.Entries.Where( e => e.EntityState != EntityState.Detached && navigation.ForeignKey.PrincipalEntityType.IsAssignableFrom(e.EntityType))) { if (navigation.IsCollection()) { if (navigation.GetCollectionAccessor().Contains(principalEntry.Entity, dependentEntity)) { return principalEntry.Entity; } } else if (navigation.GetGetter().GetClrValue(principalEntry.Entity) == dependentEntity) { return principalEntry.Entity; } } return null; }