public ItemProjectorExpression EnsureEntityIsJoined()
        {
            var dataSource = DataSource;
            var newItem    = new ExtendedExpressionReplacer(e => {
                if (e is EntityExpression)
                {
                    var entityExpression = (EntityExpression)e;
                    var typeInfo         = entityExpression.PersistentType;
                    if (typeInfo.Fields.All(fieldInfo => entityExpression.Fields.Any(entityField => entityField.Name == fieldInfo.Name)))
                    {
                        return(entityExpression);
                    }
                    var joinedIndex = typeInfo.Indexes.PrimaryIndex;
                    var joinedRs    = joinedIndex.GetQuery().Alias(Context.GetNextAlias());
                    var keySegment  = entityExpression.Key.Mapping;
                    var keyPairs    = keySegment.GetItems()
                                      .Select((leftIndex, rightIndex) => new Pair <int>(leftIndex, rightIndex))
                                      .ToArray();
                    var offset           = dataSource.Header.Length;
                    var dataSourceAsJoin = dataSource as JoinProvider;
                    dataSource           = entityExpression.IsNullable || (dataSourceAsJoin != null && dataSourceAsJoin.JoinType == JoinType.LeftOuter)
            ? dataSource.LeftJoin(joinedRs, keyPairs)
            : dataSource.Join(joinedRs, keyPairs);
                    EntityExpression.Fill(entityExpression, offset);
                    return(entityExpression);
                }
                if (e is EntityFieldExpression)
                {
                    var entityFieldExpression = (EntityFieldExpression)e;
                    if (entityFieldExpression.Entity != null)
                    {
                        return(entityFieldExpression.Entity);
                    }
                    var typeInfo    = entityFieldExpression.PersistentType;
                    var joinedIndex = typeInfo.Indexes.PrimaryIndex;
                    var joinedRs    = joinedIndex.GetQuery().Alias(Context.GetNextAlias());
                    var keySegment  = entityFieldExpression.Mapping;
                    var keyPairs    = keySegment.GetItems()
                                      .Select((leftIndex, rightIndex) => new Pair <int>(leftIndex, rightIndex))
                                      .ToArray();
                    var offset           = dataSource.Header.Length;
                    var dataSourceAsJoin = dataSource as JoinProvider;
                    dataSource           = entityFieldExpression.IsNullable || (dataSourceAsJoin != null && dataSourceAsJoin.JoinType == JoinType.LeftOuter)
            ? dataSource.LeftJoin(joinedRs, keyPairs)
            : dataSource.Join(joinedRs, keyPairs);
                    entityFieldExpression.RegisterEntityExpression(offset);
                    return(entityFieldExpression.Entity);
                }
                if (e is FieldExpression)
                {
                    var fe = (FieldExpression)e;
                    if (fe.ExtendedType == ExtendedExpressionType.Field)
                    {
                        return(fe.RemoveOwner());
                    }
                }
                return(null);
            })
                             .Replace(Item);

            return(new ItemProjectorExpression(newItem, dataSource, Context));
        }
        public ItemProjectorExpression EnsureEntityIsJoined()
        {
            var dataSource = DataSource;
            var newItem    = new ExtendedExpressionReplacer(e => {
                if (e is EntityExpression entityExpression)
                {
                    var typeInfo = entityExpression.PersistentType;

                    // Converted from LINQ to get rid of 2 closure allocations
                    var all = true;
                    foreach (var fieldInfo in typeInfo.Fields)
                    {
                        var isUsedInEntityExpression = false;
                        foreach (var entityField in entityExpression.Fields)
                        {
                            if (string.Equals(entityField.Name, fieldInfo.Name, StringComparison.Ordinal))
                            {
                                isUsedInEntityExpression = true;
                                break;
                            }
                        }
                        if (!isUsedInEntityExpression)
                        {
                            all = false;
                            break;
                        }
                    }

                    if (all)
                    {
                        return(entityExpression);
                    }

                    var joinedIndex = typeInfo.Indexes.PrimaryIndex;
                    var joinedRs    = joinedIndex.GetQuery().Alias(Context.GetNextAlias());
                    var keySegment  = entityExpression.Key.Mapping;
                    var keyPairs    = new Pair <int> [keySegment.Length];
                    var rightIndex  = 0;
                    foreach (var leftIndex in keySegment.GetItems())
                    {
                        keyPairs[rightIndex] = new Pair <int>(leftIndex, rightIndex);
                        rightIndex++;
                    }
                    var offset = dataSource.Header.Length;
                    dataSource = entityExpression.IsNullable ||
                                 (dataSource is JoinProvider dataSourceAsJoin && dataSourceAsJoin.JoinType == JoinType.LeftOuter)
              ? dataSource.LeftJoin(joinedRs, keyPairs)
              : dataSource.Join(joinedRs, keyPairs);
                    EntityExpression.Fill(entityExpression, offset);
                    return(entityExpression);
                }

                if (e is EntityFieldExpression entityFieldExpression)
                {
                    if (entityFieldExpression.Entity != null)
                    {
                        return(entityFieldExpression.Entity);
                    }

                    var typeInfo    = entityFieldExpression.PersistentType;
                    var joinedIndex = typeInfo.Indexes.PrimaryIndex;
                    var joinedRs    = joinedIndex.GetQuery().Alias(Context.GetNextAlias());
                    var keySegment  = entityFieldExpression.Mapping;
                    var keyPairs    = new Pair <int> [keySegment.Length];
                    var rightIndex  = 0;
                    foreach (var leftIndex in keySegment.GetItems())
                    {
                        keyPairs[rightIndex] = new Pair <int>(leftIndex, rightIndex);
                        rightIndex++;
                    }
                    var offset = dataSource.Header.Length;
                    dataSource = entityFieldExpression.IsNullable ||
                                 (dataSource is JoinProvider dataSourceAsJoin && dataSourceAsJoin.JoinType == JoinType.LeftOuter)
              ? dataSource.LeftJoin(joinedRs, keyPairs)
              : dataSource.Join(joinedRs, keyPairs);
                    entityFieldExpression.RegisterEntityExpression(offset);
                    return(entityFieldExpression.Entity);
                }

                if (e is FieldExpression fe && fe.ExtendedType == ExtendedExpressionType.Field)
                {
                    return(fe.RemoveOwner());
                }

                return(null);
            })
                             .Replace(Item);

            return(new ItemProjectorExpression(newItem, dataSource, Context));
        }