private object GetTargetEntity(
            IEntityType targetEntityType,
            EntityKeyFactory entityKeyFactory,
            IReadOnlyList <IProperty> keyProperties,
            EntityLoadInfo entityLoadInfo,
            ICollection <BufferedEntity> bufferedEntities,
            bool querySourceRequiresTracking)
        {
            var entityKey
                = entityKeyFactory
                  .Create(targetEntityType, keyProperties, entityLoadInfo.ValueReader);

            var targetEntity
                = GetEntity(
                      targetEntityType,
                      entityKey,
                      entityLoadInfo,
                      querySourceRequiresTracking);

            if (targetEntity != null)
            {
                List <BufferedEntity> bufferedTargetEntities;
                bufferedEntities.Add(
                    _byEntityInstance.TryGetValue(targetEntity, out bufferedTargetEntities)
                        ? bufferedTargetEntities[0]
                        : new BufferedEntity(targetEntityType, entityLoadInfo.ValueReader)
                {
                    Instance = targetEntity
                });
            }

            return(targetEntity);
        }
        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)
            {
                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 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;
        }
        private object GetTargetEntity(
            IEntityType targetEntityType,
            EntityKeyFactory entityKeyFactory,
            IReadOnlyList<IProperty> keyProperties,
            EntityLoadInfo entityLoadInfo,
            ICollection<BufferedEntity> bufferedEntities,
            bool querySourceRequiresTracking)
        {
            var entityKey
                = entityKeyFactory
                    .Create(targetEntityType, keyProperties, entityLoadInfo.ValueReader);

            var targetEntity
                = GetEntity(
                    targetEntityType,
                    entityKey,
                    entityLoadInfo,
                    querySourceRequiresTracking);

            if (targetEntity != null)
            {
                List<BufferedEntity> bufferedTargetEntities;
                bufferedEntities.Add(
                    _byEntityInstance.TryGetValue(targetEntity, out bufferedTargetEntities)
                        ? bufferedTargetEntities[0]
                        : new BufferedEntity(targetEntityType, entityLoadInfo.ValueReader)
                            {
                                Instance = targetEntity
                            });
            }

            return targetEntity;
        }