public virtual InternalEntityEntry StartTracking( IEntityType entityType, EntityKey entityKey, object entity, ValueBuffer valueBuffer) { if (entityKey == EntityKey.InvalidEntityKey) { throw new InvalidOperationException(Strings.InvalidPrimaryKey(entityType.DisplayName())); } var existingEntry = TryGetEntry(entityKey); if (existingEntry != null) { if (existingEntry.Entity != entity) { throw new InvalidOperationException(Strings.IdentityConflict(entityType.DisplayName())); } return existingEntry; } var newEntry = _subscriber.SnapshotAndSubscribe(_factory.Create(this, entityType, entity, valueBuffer)); _identityMap.Add(entityKey, newEntry); _entityReferenceMap[entity] = newEntry; newEntry.SetEntityState(EntityState.Unchanged); return newEntry; }
public virtual object GetEntity( IEntityType entityType, EntityKey entityKey, EntityLoadInfo entityLoadInfo, bool queryStateManager) { // hot path Debug.Assert(entityType != null); Debug.Assert(entityKey != null); if (entityKey == EntityKey.InvalidEntityKey) { throw new InvalidOperationException( Strings.InvalidEntityKeyOnQuery(entityType.DisplayName())); } if (queryStateManager) { var entry = _stateManager.TryGetEntry(entityKey); if (entry != null) { return entry.Entity; } } object entity; WeakReference<object> weakReference; if (!_identityMap.TryGetValue(entityKey, out weakReference) || !weakReference.TryGetTarget(out entity)) { entity = entityLoadInfo.Materialize(); if (weakReference != null) { weakReference.SetTarget(entity); } else { GarbageCollectIdentityMap(); _identityMap.Add(entityKey, new WeakReference<object>(entity)); } _valueBuffers.Add(entity, entityLoadInfo.ValueBuffer); } return entity; }
public virtual object GetEntity( IEntityType entityType, EntityKey entityKey, EntityLoadInfo entityLoadInfo, bool queryStateManager) { // hot path Debug.Assert(entityType != null); Debug.Assert(entityKey != null); if (entityKey == EntityKey.InvalidEntityKey) { return null; } if (queryStateManager) { var entry = _stateManager.TryGetEntry(entityKey); if (entry != null) { return entry.Entity; } } BufferedEntity bufferedEntity; if (!_byEntityKey.TryGetValue(entityKey, out bufferedEntity)) { bufferedEntity = new BufferedEntity(entityType, entityLoadInfo.ValueReader) { // TODO: Optimize this by not materializing when not required for query execution. i.e. // entity is only needed in final results Instance = entityLoadInfo.Materialize() }; _byEntityKey.Add(entityKey, bufferedEntity); _byEntityInstance.Add(bufferedEntity.Instance, new List<BufferedEntity> { bufferedEntity }); } return bufferedEntity.Instance; }
public virtual void UpdateDependentMap(InternalEntityEntry entry, EntityKey oldKey, IForeignKey foreignKey) { if (entry.EntityState == EntityState.Detached) { return; } var newKey = entry.GetDependentKeyValue(foreignKey); if (oldKey.Equals(newKey)) { return; } Dictionary<EntityKey, HashSet<InternalEntityEntry>> fkMap; if (_dependentsMap.TryGetValue(foreignKey, out fkMap)) { HashSet<InternalEntityEntry> dependents; if (oldKey != EntityKey.InvalidEntityKey && fkMap.TryGetValue(oldKey, out dependents)) { dependents.Remove(entry); if (dependents.Count == 0) { fkMap.Remove(oldKey); } } if (newKey == EntityKey.InvalidEntityKey) { if (fkMap.Count == 0) { _dependentsMap.Remove(foreignKey); } } else { if (!fkMap.TryGetValue(newKey, out dependents)) { dependents = new HashSet<InternalEntityEntry>(); fkMap[newKey] = dependents; } dependents.Add(entry); } } }
public virtual void UpdateIdentityMap(InternalEntityEntry entry, EntityKey oldKey, IKey principalKey) { if (entry.EntityState == EntityState.Detached) { return; } var newKey = GetKeyValueChecked(principalKey, entry); if (oldKey.Equals(newKey)) { return; } InternalEntityEntry existingEntry; if (_identityMap.TryGetValue(newKey, out existingEntry) && existingEntry != entry) { throw new InvalidOperationException(CoreStrings.IdentityConflict(entry.EntityType.Name)); } _identityMap.Remove(oldKey); if (newKey != EntityKey.InvalidEntityKey) { _identityMap[newKey] = entry; } }
public virtual InternalEntityEntry TryGetEntry(EntityKey keyValue) { InternalEntityEntry entry; _identityMap.TryGetValue(keyValue, out entry); return entry; }
private void AddToIdentityMap(IEntityType entityType, EntityKey entityKey, InternalEntityEntry newEntry) { _identityMap.Add(entityKey, newEntry); foreach (var key in entityType.GetKeys().Where(k => k != entityKey.Key)) { var principalKeyValue = newEntry.GetPrincipalKeyValue(key); if (principalKeyValue != EntityKey.InvalidEntityKey) { _identityMap[principalKeyValue] = newEntry; } } foreach (var foreignKey in entityType.GetForeignKeys()) { var dependentKey = newEntry.GetDependentKeyValue(foreignKey); if (dependentKey == EntityKey.InvalidEntityKey) { continue; } Dictionary<EntityKey, HashSet<InternalEntityEntry>> fkMap; if (!_dependentsMap.TryGetValue(foreignKey, out fkMap)) { fkMap = new Dictionary<EntityKey, HashSet<InternalEntityEntry>>(); _dependentsMap[foreignKey] = fkMap; } HashSet<InternalEntityEntry> dependents; if (!fkMap.TryGetValue(dependentKey, out dependents)) { dependents = new HashSet<InternalEntityEntry>(); fkMap[dependentKey] = dependents; } dependents.Add(newEntry); } }
private IEntityType IncludeCore( object entity, INavigation navigation, out EntityKey primaryKey, out Func<ValueBuffer, EntityKey> relatedKeyFactory) { var primaryKeyFactory = _entityKeyFactorySource .GetKeyFactory(navigation.ForeignKey.PrincipalKey.Properties); var foreignKeyFactory = _entityKeyFactorySource .GetKeyFactory(navigation.ForeignKey.Properties); var targetEntityType = navigation.GetTargetType(); object boxedValueBuffer; if (!_valueBuffers.TryGetValue(entity, out boxedValueBuffer)) { var entry = _stateManager.TryGetEntry(entity); Debug.Assert(entry != null); primaryKey = navigation.PointsToPrincipal() ? entry.GetDependentKeySnapshot(navigation.ForeignKey) : entry.GetPrimaryKeyValue(); } else { primaryKey = navigation.PointsToPrincipal() ? foreignKeyFactory .Create( targetEntityType.RootType(), navigation.ForeignKey.Properties, (ValueBuffer)boxedValueBuffer) : primaryKeyFactory .Create( navigation.DeclaringEntityType.RootType(), navigation.ForeignKey.PrincipalKey.Properties, (ValueBuffer)boxedValueBuffer); } if (navigation.PointsToPrincipal()) { relatedKeyFactory = valueBuffer => primaryKeyFactory .Create( targetEntityType.RootType(), navigation.ForeignKey.PrincipalKey.Properties, valueBuffer); } else { relatedKeyFactory = valueBuffer => foreignKeyFactory .Create( navigation.DeclaringEntityType.RootType(), navigation.ForeignKey.Properties, valueBuffer); } return targetEntityType; }
private IEntityType IncludeCore( object entity, INavigation navigation, out EntityKey primaryKey, out List<BufferedEntity> bufferedEntities, out Func<IValueReader, EntityKey> relatedKeyFactory) { var primaryKeyFactory = _entityKeyFactorySource .GetKeyFactory(navigation.ForeignKey.PrincipalKey.Properties); var foreignKeyFactory = _entityKeyFactorySource .GetKeyFactory(navigation.ForeignKey.Properties); var targetEntityType = navigation.GetTargetType(); if (!_byEntityInstance.TryGetValue(entity, out bufferedEntities)) { _byEntityInstance.Add(entity, bufferedEntities = new List<BufferedEntity> { null }); var entry = _stateManager.TryGetEntry(entity); Debug.Assert(entry != null); primaryKey = navigation.PointsToPrincipal ? entry.GetDependentKeySnapshot(navigation.ForeignKey) : entry.GetPrimaryKeyValue(); } else { // if entity is already in state manager it can't be added to the buffer. 'null' value was added to signify that // this means relevant key should be acquired from state manager rather than buffered reader if (bufferedEntities[0] == null) { var entry = _stateManager.TryGetEntry(entity); Debug.Assert(entry != null); primaryKey = navigation.PointsToPrincipal ? entry.GetDependentKeySnapshot(navigation.ForeignKey) : entry.GetPrimaryKeyValue(); } else { primaryKey = navigation.PointsToPrincipal ? foreignKeyFactory .Create( targetEntityType, navigation.ForeignKey.Properties, bufferedEntities[0].ValueReader) : primaryKeyFactory .Create( navigation.EntityType, navigation.ForeignKey.PrincipalKey.Properties, bufferedEntities[0].ValueReader); } } if (navigation.PointsToPrincipal) { relatedKeyFactory = valueReader => primaryKeyFactory .Create( targetEntityType, navigation.ForeignKey.PrincipalKey.Properties, valueReader); } else { relatedKeyFactory = valueReader => foreignKeyFactory .Create( navigation.EntityType, navigation.ForeignKey.Properties, valueReader); } return targetEntityType; }