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;
        }
Example #3
0
        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;
        }
Example #9
0
        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;
        }