private void InitialFixup( InternalEntityEntry entry, ISet <IForeignKey> handledForeignKeys, bool fromQuery) { var entityType = (EntityType)entry.EntityType; var stateManager = entry.StateManager; foreach (var foreignKey in entityType.GetForeignKeys()) { if (handledForeignKeys == null || !handledForeignKeys.Contains(foreignKey)) { var principalEntry = stateManager.GetPrincipal(entry, foreignKey); if (principalEntry != null) { if (!foreignKey.PrincipalEntityType.IsAssignableFrom(principalEntry.EntityType)) { if (_sensitiveLoggingEnabled) { throw new InvalidOperationException(CoreStrings.IncompatiblePrincipalEntrySensitive( entry.BuildCurrentValuesString(foreignKey.Properties), entityType.DisplayName(), entry.BuildOriginalValuesString(entityType.FindPrimaryKey().Properties), principalEntry.EntityType.DisplayName(), foreignKey.PrincipalEntityType.DisplayName())); } throw new InvalidOperationException(CoreStrings.IncompatiblePrincipalEntry( Property.Format(foreignKey.Properties), entityType.DisplayName(), principalEntry.EntityType.DisplayName(), foreignKey.PrincipalEntityType.DisplayName())); } // Set navigation to principal based on FK properties SetNavigation(entry, foreignKey.DependentToPrincipal, principalEntry); // Add this entity to principal's collection, or set inverse for 1:1 ToDependentFixup(entry, principalEntry, foreignKey); } } } foreach (var foreignKey in entityType.GetReferencingForeignKeys()) { if (handledForeignKeys == null || !handledForeignKeys.Contains(foreignKey)) { var dependents = stateManager.GetDependents(entry, foreignKey); if (foreignKey.IsUnique) { var dependentEntry = dependents.FirstOrDefault(); if (dependentEntry != null) { // Set navigations to and from principal entity that is indicated by FK SetNavigation(entry, foreignKey.PrincipalToDependent, dependentEntry); SetNavigation(dependentEntry, foreignKey.DependentToPrincipal, entry); } } else { foreach (var dependentEntry in dependents) { // Add to collection on principal indicated by FK and set inverse navigation AddToCollection(entry, foreignKey.PrincipalToDependent, dependentEntry); SetNavigation(dependentEntry, foreignKey.DependentToPrincipal, entry); } } } } // If the new state is from a query then we are going to assume that the FK value is the source of // truth and not attempt to ascertain relationships from navigation properties if (!fromQuery) { var setModified = entry.EntityState != EntityState.Unchanged && entry.EntityState != EntityState.Modified; foreach (var foreignKey in entityType.GetReferencingForeignKeys()) { var principalToDependent = foreignKey.PrincipalToDependent; if (principalToDependent != null) { var navigationValue = entry[principalToDependent]; if (navigationValue != null) { if (principalToDependent.IsCollection()) { var dependents = ((IEnumerable)navigationValue).Cast <object>().ToList(); foreach (var dependentEntity in dependents) { var dependentEntry = stateManager.TryGetEntry(dependentEntity); if (dependentEntry == null || dependentEntry.EntityState == EntityState.Detached) { // If dependents in collection are not yet tracked, then save them away so that // when we start tracking them we can come back and fixup this principal to them stateManager.RecordReferencedUntrackedEntity(dependentEntity, principalToDependent, entry); } else { FixupToDependent(entry, dependentEntry, foreignKey, setModified); } } } else { var targetEntityType = principalToDependent.GetTargetType(); var dependentEntry = stateManager.TryGetEntry(navigationValue, targetEntityType); if (dependentEntry == null || dependentEntry.EntityState == EntityState.Detached) { // If dependent is not yet tracked, then save it away so that // when we start tracking it we can come back and fixup this principal to it stateManager.RecordReferencedUntrackedEntity(navigationValue, principalToDependent, entry); } else { FixupToDependent(entry, dependentEntry, foreignKey, setModified); } } } } } foreach (var foreignKey in entityType.GetForeignKeys()) { var dependentToPrincipal = foreignKey.DependentToPrincipal; if (dependentToPrincipal != null) { var navigationValue = entry[dependentToPrincipal]; if (navigationValue != null) { var targetEntityType = dependentToPrincipal.GetTargetType(); var principalEntry = stateManager.TryGetEntry(navigationValue, targetEntityType); if (principalEntry == null || principalEntry.EntityState == EntityState.Detached) { // If principal is not yet tracked, then save it away so that // when we start tracking it we can come back and fixup this dependent to it stateManager.RecordReferencedUntrackedEntity(navigationValue, dependentToPrincipal, entry); } else { FixupToPrincipal(entry, principalEntry, foreignKey, setModified); } } } } // If the entity was previously referenced while it was still untracked, go back and do the fixup // that we would have done then now that the entity is tracked. foreach (var danglerEntry in stateManager.GetRecordedReferers(entry.Entity, clear: true)) { DelayedFixup(danglerEntry.Item2, danglerEntry.Item1, entry); } } }