protected override Expression VisitEntityQueryable([NotNull] Type elementType)
        {
            Check.NotNull(elementType, nameof(elementType));

            var entityType     = _model.FindEntityType(elementType);
            var collectionName = _annotationsProvider.For(entityType).CollectionName;

            var findExpression = _findExpressionFactory.Create();

            findExpression.SetCollectionExpression(new CollectionExpression(collectionName, elementType));

            var shaper = CreateShaper(elementType, entityType, findExpression);

            Func <IBsonQueryGenerator> createQueryGenerator = findExpression.CreateBsonQueryGenerator;
            var valueBufferShaper = _valueBufferShaperFactory.Create(findExpression);

            return(Expression.Call(
                       QueryModelVisitor.QueryCompilationContext.QueryMethodProvider
                       .ShapedQueryMethod
                       .MakeGenericMethod(shaper.Type),
                       EntityQueryModelVisitor.QueryContextParameter,
                       Expression.Constant(_shaperCommandContextFactory.Create(createQueryGenerator)),
                       Expression.Constant(shaper),
                       Expression.Constant(valueBufferShaper)));
        }
        /// <summary>
        /// Resolve read only expression
        /// </summary>
        /// <param name="elementType"></param>
        /// <returns></returns>
        protected override Expression VisitEntityQueryable([NotNull] Type elementType)
        {
            Check.NotNull(elementType, nameof(elementType));

            // create then add read only expression
            var cypherQueryCompilationContext = QueryModelVisitor
                                                .QueryCompilationContext;

            var entityType = cypherQueryCompilationContext.FindEntityType(_querySource)
                             ?? _model.FindEntityType(elementType);

            var readOnlyExpression = _readOnlyExpressionFactory
                                     .Create(cypherQueryCompilationContext);

            QueryModelVisitor.AddQuery(
                _querySource,
                readOnlyExpression
                );


            // unique node alias either from the Relinq query source if not generated or the first label
            string[] labels = entityType.Cypher().Labels;
            string   alias  = cypherQueryCompilationContext
                              .CreateUniqueNodeAlias(
                _querySource.HasGeneratedItemName()
                        ? labels[0][0].ToString().ToLowerInvariant()
                        : _querySource.ItemName
                );

            // TODO: Use from SQL annotation?
            // default match
            readOnlyExpression.AddReadingClause(
                new MatchExpression(
                    new PatternExpression(
                        new NodePatternExpression(
                            labels,
                            _querySource,
                            alias
                            )
                        )
                    )
                );

            // bundle the sql (cypher) generator inside the shaper command factory
            Func <IQuerySqlGenerator> querySqlGeneratorFunc = readOnlyExpression
                                                              .CreateDefaultQueryCypherGenerator;
            var shaper = CreateShaper(elementType, entityType, readOnlyExpression);

            return(Expression.Call(
                       QueryModelVisitor.QueryCompilationContext.QueryMethodProvider
                       .ShapedQueryMethod
                       .MakeGenericMethod(shaper.Type),
                       EntityQueryModelVisitor.QueryContextParameter,
                       Expression.Constant(_shaperCommandContextFactory.Create(querySqlGeneratorFunc)),
                       Expression.Constant(shaper)));
        }
Ejemplo n.º 3
0
        private IReadOnlyList <Func <QueryContext, TRelatedEntitiesLoader> > CreateRelatedEntitiesLoaders <TRelatedEntitiesLoader>(
            IQuerySource querySource, IEnumerable <INavigation> navigationPath)
        {
            var relatedEntitiesLoaders = new List <Func <QueryContext, TRelatedEntitiesLoader> >();

            var selectExpression
                = _queryCompilationContext.FindSelectExpression(querySource);

            var compositePredicateExpressionVisitor
                = _compositePredicateExpressionVisitorFactory.Create();

            var targetTableExpression
                = selectExpression.GetTableForQuerySource(querySource);

            var canProduceInnerJoin = true;
            var navigationCount     = 0;

            foreach (var navigation in navigationPath)
            {
                var queryIndex = _queryIndexes[navigationCount];
                navigationCount++;

                var targetEntityType = navigation.GetTargetType();
                var targetTableName  = _relationalAnnotationProvider.For(targetEntityType).TableName;
                var targetTableAlias
                    = _queryCompilationContext
                      .CreateUniqueTableAlias(targetTableName[0].ToString().ToLowerInvariant());

                if (!navigation.IsCollection())
                {
                    var joinedTableExpression
                        = new TableExpression(
                              targetTableName,
                              _relationalAnnotationProvider.For(targetEntityType).Schema,
                              targetTableAlias,
                              querySource);

                    var valueBufferOffset = selectExpression.Projection.Count;

                    canProduceInnerJoin
                        = canProduceInnerJoin &&
                          navigation.ForeignKey.IsRequired &&
                          navigation.IsDependentToPrincipal();

                    var joinExpression
                        = canProduceInnerJoin
                            ? selectExpression.AddInnerJoin(joinedTableExpression)
                            : selectExpression.AddLeftOuterJoin(joinedTableExpression);

                    var oldPredicate = selectExpression.Predicate;

                    var materializer
                        = _materializerFactory
                          .CreateMaterializer(
                              targetEntityType,
                              selectExpression,
                              (p, se) => se.AddToProjection(
                                  new AliasExpression(
                                      new ColumnExpression(
                                          _relationalAnnotationProvider.For(p).ColumnName,
                                          p,
                                          joinedTableExpression))) - valueBufferOffset,
                              querySource: null);

                    if (selectExpression.Predicate != oldPredicate)
                    {
                        selectExpression.Predicate
                            = compositePredicateExpressionVisitor
                              .Visit(selectExpression.Predicate);

                        var newJoinExpression = AdjustJoinExpression(selectExpression, joinExpression);

                        selectExpression.Predicate = oldPredicate;
                        selectExpression.RemoveTable(joinExpression);
                        selectExpression.AddTable(newJoinExpression, createUniqueAlias: false);
                        joinExpression = newJoinExpression;
                    }

                    joinExpression.Predicate
                        = BuildJoinEqualityExpression(
                              navigation,
                              navigation.IsDependentToPrincipal() ? targetTableExpression : joinExpression,
                              navigation.IsDependentToPrincipal() ? joinExpression : targetTableExpression,
                              querySource);

                    targetTableExpression = joinedTableExpression;

                    relatedEntitiesLoaders.Add(qc =>
                                               (TRelatedEntitiesLoader)_queryCompilationContext.QueryMethodProvider
                                               .CreateReferenceRelatedEntitiesLoaderMethod
                                               .Invoke(
                                                   null,
                                                   new object[]
                    {
                        valueBufferOffset,
                        queryIndex,
                        materializer.Compile()             // TODO: Used cached materializer?
                    }));
                }
                else
                {
                    var principalTable
                        = selectExpression.Tables.Count == 1 &&
                          selectExpression.Tables
                          .OfType <SelectExpression>()
                          .Any(s => s.Tables.Any(t => t.QuerySource == querySource))
                          // true when select is wrapped e.g. when RowNumber paging is enabled
                            ? selectExpression.Tables[0]
                            : selectExpression.Tables.Last(t => t.QuerySource == querySource);

                    var canGenerateExists
                        = (selectExpression.Predicate != null ||
                           selectExpression.Offset == null) &&
                          !IsOrderingOnNonPrincipalKeyProperties(
                              selectExpression.OrderBy,
                              navigation.ForeignKey.PrincipalKey.Properties);

                    foreach (var property in navigation.ForeignKey.PrincipalKey.Properties)
                    {
                        selectExpression
                        .AddToOrderBy(
                            _relationalAnnotationProvider.For(property).ColumnName,
                            property,
                            principalTable,
                            OrderingDirection.Asc);
                    }

                    var targetSelectExpression = _selectExpressionFactory.Create(_queryCompilationContext);

                    targetTableExpression
                        = new TableExpression(
                              targetTableName,
                              _relationalAnnotationProvider.For(targetEntityType).Schema,
                              targetTableAlias,
                              querySource);

                    targetSelectExpression.AddTable(targetTableExpression, createUniqueAlias: false);

                    var materializer
                        = _materializerFactory
                          .CreateMaterializer(
                              targetEntityType,
                              targetSelectExpression,
                              (p, se) => se.AddToProjection(
                                  _relationalAnnotationProvider.For(p).ColumnName,
                                  p,
                                  querySource),
                              querySource: null);

                    if (canGenerateExists)
                    {
                        var subqueryExpression = selectExpression.Clone();
                        subqueryExpression.ClearProjection();
                        subqueryExpression.ClearOrderBy();
                        subqueryExpression.IsProjectStar = false;

                        var subqueryTable
                            = subqueryExpression.Tables.Count == 1 &&
                              subqueryExpression.Tables
                              .OfType <SelectExpression>()
                              .Any(s => s.Tables.Any(t => t.QuerySource == querySource))
                              // true when select is wrapped e.g. when RowNumber paging is enabled
                                ? subqueryExpression.Tables[0]
                                : subqueryExpression.Tables.Last(t => t.QuerySource == querySource);

                        var existsPredicateExpression = new ExistsExpression(subqueryExpression);

                        AddToPredicate(targetSelectExpression, existsPredicateExpression);

                        AddToPredicate(subqueryExpression, BuildJoinEqualityExpression(navigation, targetTableExpression, subqueryTable, querySource));

                        subqueryExpression.Predicate
                            = compositePredicateExpressionVisitor
                              .Visit(subqueryExpression.Predicate);

                        var pkPropertiesToFkPropertiesMap = navigation.ForeignKey.PrincipalKey.Properties
                                                            .Zip(navigation.ForeignKey.Properties, (k, v) => new { PkProperty = k, FkProperty = v })
                                                            .ToDictionary(x => x.PkProperty, x => x.FkProperty);

                        foreach (var ordering in selectExpression.OrderBy)
                        {
                            // ReSharper disable once PossibleNullReferenceException
                            var principalKeyProperty         = ((ordering.Expression as AliasExpression)?.Expression as ColumnExpression).Property;
                            var referencedForeignKeyProperty = pkPropertiesToFkPropertiesMap[principalKeyProperty];
                            targetSelectExpression
                            .AddToOrderBy(
                                _relationalAnnotationProvider.For(referencedForeignKeyProperty).ColumnName,
                                referencedForeignKeyProperty,
                                targetTableExpression,
                                ordering.OrderingDirection);
                        }
                    }
                    else
                    {
                        var innerJoinSelectExpression
                            = selectExpression.Clone(
                                  selectExpression.OrderBy
                                  .Select(o => o.Expression)
                                  .Last(o => o.IsAliasWithColumnExpression())
                                  .TryGetColumnExpression().TableAlias);

                        innerJoinSelectExpression.ClearProjection();

                        var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression);

                        LiftOrderBy(innerJoinSelectExpression, targetSelectExpression, innerJoinExpression);

                        innerJoinSelectExpression.IsDistinct = true;

                        innerJoinExpression.Predicate
                            = BuildJoinEqualityExpression(
                                  navigation,
                                  targetTableExpression,
                                  innerJoinExpression,
                                  querySource);
                    }

                    targetSelectExpression.Predicate
                        = compositePredicateExpressionVisitor
                          .Visit(targetSelectExpression.Predicate);

                    selectExpression = targetSelectExpression;

                    relatedEntitiesLoaders.Add(qc =>
                                               (TRelatedEntitiesLoader)_queryCompilationContext.QueryMethodProvider
                                               .CreateCollectionRelatedEntitiesLoaderMethod
                                               .Invoke(
                                                   null,
                                                   new object[]
                    {
                        qc,
                        _shaperCommandContextFactory.Create(() =>
                                                            _querySqlGeneratorFactory.CreateDefault(targetSelectExpression)),
                        queryIndex,
                        materializer.Compile()             // TODO: Used cached materializer?
                    }));
                }
            }

            return(relatedEntitiesLoaders);
        }
Ejemplo n.º 4
0
        protected override Expression VisitEntityQueryable(Type elementType)
        {
            var relationalQueryCompilationContext = QueryModelVisitor.QueryCompilationContext;

            var entityType = relationalQueryCompilationContext.FindEntityType(_querySource)
                             ?? _model.FindEntityType(elementType);

            var selectExpression = _selectExpressionFactory.Create(relationalQueryCompilationContext);

            QueryModelVisitor.AddQuery(_querySource, selectExpression);

            var tableName    = entityType.Relational().TableName;
            var databaseName = elementType.CustomAttributes
                               .FirstOrDefault(c => c.AttributeType == typeof(DatabaseNameAttribute))
                               ?.ConstructorArguments[0]
                               .Value
                               .ToString();

            var tableAlias
                = relationalQueryCompilationContext.CreateUniqueTableAlias(
                      _querySource.HasGeneratedItemName()
                        ? tableName[0].ToString(CultureInfo.InvariantCulture).ToUpperInvariant()
                        : (_querySource as GroupJoinClause)?.JoinClause.ItemName
                      ?? _querySource.ItemName);

            var fromSqlAnnotation
                = relationalQueryCompilationContext
                  .QueryAnnotations
                  .OfType <FromSqlResultOperator>()
                  .LastOrDefault(a => a.QuerySource == _querySource);

            Func <IQuerySqlGenerator> querySqlGeneratorFunc = selectExpression.CreateDefaultQuerySqlGenerator;

            if (fromSqlAnnotation == null)
            {
                selectExpression.AddTable(
                    new TableExpression(
                        databaseName,
                        tableName,
                        entityType.Relational().Schema,
                        tableAlias,
                        _querySource));
            }
            else
            {
                selectExpression.AddTable(
                    new FromSqlExpression(
                        fromSqlAnnotation.Sql,
                        fromSqlAnnotation.Arguments,
                        tableAlias,
                        _querySource));

                var trimmedSql = fromSqlAnnotation.Sql.TrimStart('\r', '\n', '\t', ' ');

                var useQueryComposition
                    = trimmedSql.StartsWith("SELECT ", StringComparison.OrdinalIgnoreCase) ||
                      trimmedSql.StartsWith("SELECT" + Environment.NewLine, StringComparison.OrdinalIgnoreCase) ||
                      trimmedSql.StartsWith("SELECT\t", StringComparison.OrdinalIgnoreCase);

                var requiresClientEval = !useQueryComposition;

                if (!useQueryComposition &&
                    relationalQueryCompilationContext.IsIncludeQuery)
                {
                    throw new InvalidOperationException(
                              RelationalStrings.StoredProcedureIncludeNotSupported);
                }

                if (useQueryComposition &&
                    fromSqlAnnotation.QueryModel.IsIdentityQuery() &&
                    !fromSqlAnnotation.QueryModel.ResultOperators.Any() &&
                    !relationalQueryCompilationContext.IsIncludeQuery &&
                    entityType.BaseType == null &&
                    !entityType.GetDerivedTypes().Any())
                {
                    useQueryComposition = false;
                }

                if (!useQueryComposition)
                {
                    QueryModelVisitor.RequiresClientEval = requiresClientEval;

                    querySqlGeneratorFunc = ()
                                            => selectExpression.CreateFromSqlQuerySqlGenerator(
                        fromSqlAnnotation.Sql,
                        fromSqlAnnotation.Arguments);
                }
            }

            var shaper = CreateShaper(elementType, entityType, selectExpression);

            DiscriminateProjectionQuery(entityType, selectExpression, _querySource);

            return(Expression.Call(
                       QueryModelVisitor.QueryCompilationContext.QueryMethodProvider
                       .ShapedQueryMethod
                       .MakeGenericMethod(shaper.Type),
                       EntityQueryModelVisitor.QueryContextParameter,
                       Expression.Constant(_shaperCommandContextFactory.Create(querySqlGeneratorFunc)),
                       Expression.Constant(shaper)));
        }
Ejemplo n.º 5
0
        private IEnumerable <Expression> CreateIncludeRelatedValuesStrategyFactories(
            IQuerySource querySource,
            IEnumerable <INavigation> navigationPath)
        {
            var selectExpression
                = _queryCompilationContext.FindSelectExpression(querySource);

            var targetTableExpression
                = selectExpression.GetTableForQuerySource(querySource);

            var canProduceInnerJoin = true;
            var navigationCount     = 0;

            foreach (var navigation in navigationPath)
            {
                var queryIndex = _queryIndexes[navigationCount];
                navigationCount++;

                var targetEntityType = navigation.GetTargetType();
                var targetTableName  = _relationalAnnotationProvider.For(targetEntityType).TableName;
                var targetTableAlias = targetTableName[0].ToString().ToLower();

                if (!navigation.IsCollection())
                {
                    var joinedTableExpression
                        = new TableExpression(
                              targetTableName,
                              _relationalAnnotationProvider.For(targetEntityType).Schema,
                              targetTableAlias,
                              querySource);

                    var valueBufferOffset = selectExpression.Projection.Count;

                    canProduceInnerJoin
                        = canProduceInnerJoin && navigation.ForeignKey.IsRequired && navigation.IsDependentToPrincipal();

                    var joinExpression
                        = canProduceInnerJoin
                            ? selectExpression
                          .AddInnerJoin(joinedTableExpression)
                            : selectExpression
                          .AddOuterJoin(joinedTableExpression);

                    var oldPredicate = selectExpression.Predicate;

                    var materializer
                        = _materializerFactory
                          .CreateMaterializer(
                              targetEntityType,
                              selectExpression,
                              (p, se) => se.AddToProjection(
                                  new AliasExpression(
                                      new ColumnExpression(
                                          _relationalAnnotationProvider.For(p).ColumnName,
                                          p,
                                          joinedTableExpression))) - valueBufferOffset,
                              querySource: null);

                    if (selectExpression.Predicate != oldPredicate)
                    {
                        var newJoinExpression = AdjustJoinExpression(selectExpression, joinExpression);

                        selectExpression.Predicate = oldPredicate;
                        selectExpression.RemoveTable(joinExpression);
                        selectExpression.AddTable(newJoinExpression);
                        joinExpression = newJoinExpression;
                    }

                    joinExpression.Predicate
                        = BuildJoinEqualityExpression(
                              navigation,
                              navigation.IsDependentToPrincipal() ? targetTableExpression : joinExpression,
                              navigation.IsDependentToPrincipal() ? joinExpression : targetTableExpression,
                              querySource);

                    targetTableExpression = joinedTableExpression;

                    yield return
                        (Expression.Lambda(
                             Expression.Call(
                                 _queryCompilationContext.QueryMethodProvider
                                 .CreateReferenceIncludeRelatedValuesStrategyMethod,
                                 Expression.Convert(
                                     EntityQueryModelVisitor.QueryContextParameter,
                                     typeof(RelationalQueryContext)),
                                 Expression.Constant(valueBufferOffset),
                                 Expression.Constant(queryIndex),
                                 materializer)));
                }
                else
                {
                    var principalTable
                        = selectExpression.Tables.Last(t => t.QuerySource == querySource);

                    foreach (var property in navigation.ForeignKey.PrincipalKey.Properties)
                    {
                        selectExpression
                        .AddToOrderBy(
                            _relationalAnnotationProvider.For(property).ColumnName,
                            property,
                            principalTable,
                            OrderingDirection.Asc);
                    }

                    var targetSelectExpression = _selectExpressionFactory.Create();

                    targetTableExpression
                        = new TableExpression(
                              targetTableName,
                              _relationalAnnotationProvider.For(targetEntityType).Schema,
                              targetTableAlias,
                              querySource);

                    targetSelectExpression.AddTable(targetTableExpression);

                    var materializer
                        = _materializerFactory
                          .CreateMaterializer(
                              targetEntityType,
                              targetSelectExpression,
                              (p, se) => se.AddToProjection(
                                  _relationalAnnotationProvider.For(p).ColumnName,
                                  p,
                                  querySource),
                              querySource: null);

                    var innerJoinSelectExpression
                        = selectExpression.Clone(
                              selectExpression.OrderBy
                              .Select(o => o.Expression)
                              .Last(o => o.IsAliasWithColumnExpression())
                              .TryGetColumnExpression().TableAlias);

                    innerJoinSelectExpression.IsDistinct = true;
                    innerJoinSelectExpression.ClearProjection();

                    var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression);

                    LiftOrderBy(innerJoinSelectExpression, targetSelectExpression, innerJoinExpression);

                    innerJoinExpression.Predicate
                        = BuildJoinEqualityExpression(
                              navigation,
                              targetTableExpression,
                              innerJoinExpression,
                              querySource);

                    selectExpression = targetSelectExpression;

                    yield return
                        (Expression.Lambda(
                             Expression.Call(
                                 _queryCompilationContext.QueryMethodProvider
                                 .CreateCollectionIncludeRelatedValuesStrategyMethod,
                                 Expression.Call(
                                     _queryCompilationContext.QueryMethodProvider.QueryMethod,
                                     EntityQueryModelVisitor.QueryContextParameter,
                                     Expression.Constant(
                                         _shaperCommandContextFactory.Create(
                                             () => _querySqlGeneratorFactory
                                             .CreateDefault(targetSelectExpression))),
                                     Expression.Constant(queryIndex, typeof(int?))),
                                 materializer)));
                }
            }
        }
Ejemplo n.º 6
0
        protected override Expression VisitEntityQueryable(Type elementType)
        {
            Check.NotNull(elementType, nameof(elementType));

            var relationalQueryCompilationContext = QueryModelVisitor.QueryCompilationContext;
            var entityType = _model.FindEntityType(elementType);

            var selectExpression = _selectExpressionFactory.Create(relationalQueryCompilationContext);

            QueryModelVisitor.AddQuery(_querySource, selectExpression);

            var name = _relationalAnnotationProvider.For(entityType).TableName;

            var tableAlias
                = _querySource.HasGeneratedItemName()
                    ? name[0].ToString().ToLowerInvariant()
                    : _querySource.ItemName;

            var fromSqlAnnotation
                = relationalQueryCompilationContext
                  .QueryAnnotations
                  .OfType <FromSqlResultOperator>()
                  .LastOrDefault(a => a.QuerySource == _querySource);

            Func <IQuerySqlGenerator> querySqlGeneratorFunc = selectExpression.CreateDefaultQuerySqlGenerator;

            if (fromSqlAnnotation == null)
            {
                selectExpression.AddTable(
                    new TableExpression(
                        name,
                        _relationalAnnotationProvider.For(entityType).Schema,
                        tableAlias,
                        _querySource));
            }
            else
            {
                selectExpression.AddTable(
                    new FromSqlExpression(
                        fromSqlAnnotation.Sql,
                        fromSqlAnnotation.Arguments,
                        tableAlias,
                        _querySource));

                var useQueryComposition
                    = fromSqlAnnotation.Sql
                      .TrimStart()
                      .StartsWith("SELECT ", StringComparison.OrdinalIgnoreCase);

                if (!useQueryComposition)
                {
                    if (relationalQueryCompilationContext.IsIncludeQuery)
                    {
                        throw new InvalidOperationException(
                                  RelationalStrings.StoredProcedureIncludeNotSupported);
                    }
                }

                if (useQueryComposition &&
                    fromSqlAnnotation.QueryModel.IsIdentityQuery() &&
                    !fromSqlAnnotation.QueryModel.ResultOperators.Any() &&
                    !relationalQueryCompilationContext.IsIncludeQuery)
                {
                    useQueryComposition = false;
                }

                if (!useQueryComposition)
                {
                    QueryModelVisitor.RequiresClientEval = true;

                    querySqlGeneratorFunc = ()
                                            => selectExpression.CreateFromSqlQuerySqlGenerator(
                        fromSqlAnnotation.Sql,
                        fromSqlAnnotation.Arguments);
                }
            }

            var shaper = CreateShaper(elementType, entityType, selectExpression);

            return(Expression.Call(
                       QueryModelVisitor.QueryCompilationContext.QueryMethodProvider // TODO: Don't use ShapedQuery when projecting
                       .ShapedQueryMethod
                       .MakeGenericMethod(shaper.Type),
                       EntityQueryModelVisitor.QueryContextParameter,
                       Expression.Constant(_shaperCommandContextFactory.Create(querySqlGeneratorFunc)),
                       Expression.Constant(shaper)));
        }
        protected override Expression VisitEntityQueryable(Type elementType)
        {
            if (elementType == null)
            {
                throw new ArgumentNullException(nameof(elementType));
            }

            var relationalQueryCompilationContext = QueryModelVisitor.QueryCompilationContext;


            var valueFromOpenJsonAnnotation
                = relationalQueryCompilationContext
                  .QueryAnnotations
                  .OfType <ValueFromOpenJsonOperator>()
                  .LastOrDefault(a => a.QuerySource == _querySource);

            if (valueFromOpenJsonAnnotation != null)
            {
                if (valueFromOpenJsonAnnotation.Json.NodeType == ExpressionType.MemberAccess && valueFromOpenJsonAnnotation.Json is MemberExpression me)
                {
                    var entityType = relationalQueryCompilationContext.FindEntityType(_querySource)
                                     ?? _model.FindEntityType(elementType);
                    var selectExpression = _selectExpressionFactory.Create(relationalQueryCompilationContext);
                    QueryModelVisitor.AddQuery(_querySource, selectExpression);
                    var name = entityType.Relational().TableName;
                    var tableAlias
                        = relationalQueryCompilationContext.CreateUniqueTableAlias(
                              _querySource.HasGeneratedItemName()
                                ? name[0].ToString().ToLowerInvariant()
                                : (_querySource as GroupJoinClause)?.JoinClause.ItemName
                              ?? _querySource.ItemName);
                    Func <IQuerySqlGenerator> querySqlGeneratorFunc = selectExpression.CreateDefaultQuerySqlGenerator;

                    var memberEntityType = relationalQueryCompilationContext.Model.FindEntityType(me.Expression.Type);
                    var memberProperty   = memberEntityType.FindProperty(me.Member as PropertyInfo);

                    var expr = new ValueFromOpenJsonExpression(_querySource,
                                                               valueFromOpenJsonAnnotation.Json,
                                                               valueFromOpenJsonAnnotation.Path,
                                                               tableAlias);
                    expr.PropertyMapping[expr.Json] = memberProperty;

                    //var jsonProperties = MemberAccessBindingExpressionVisitor.GetPropertyPath(expr.Json, relationalQueryCompilationContext, out var qsr);
                    //Console.WriteLine(jsonProperties);

                    //expr = (ValueFromOpenJsonExpression)Visit(expr);
                    //expr.PropertyMapping[expr.Json] = memberProperty;

                    //expr = (ValueFromOpenJsonExpression)QueryModelVisitor.ReplaceClauseReferences(expr);
                    //expr.PropertyMapping[expr.Json] = memberProperty;

                    selectExpression.AddTable(expr);

                    //var trimmedSql = valueFromOpenJsonAnnotation.Sql.TrimStart('\r', '\n', '\t', ' ');
                    var useQueryComposition = true;
                    //= trimmedSql.StartsWith("SELECT ", StringComparison.OrdinalIgnoreCase)
                    //  || trimmedSql.StartsWith("SELECT" + Environment.NewLine, StringComparison.OrdinalIgnoreCase)
                    //  || trimmedSql.StartsWith("SELECT\t", StringComparison.OrdinalIgnoreCase);
                    var requiresClientEval = !useQueryComposition;
                    if (!useQueryComposition)
                    {
                        if (relationalQueryCompilationContext.IsIncludeQuery)
                        {
                            throw new InvalidOperationException(
                                      RelationalStrings.StoredProcedureIncludeNotSupported);
                        }
                    }
                    if (useQueryComposition &&
                        valueFromOpenJsonAnnotation.QueryModel.IsIdentityQuery() &&
                        !valueFromOpenJsonAnnotation.QueryModel.ResultOperators.Any() &&
                        !relationalQueryCompilationContext.IsIncludeQuery)
                    {
                        useQueryComposition = false;
                    }

                    if (!useQueryComposition)
                    {
                        throw new NotImplementedException();
                        //QueryModelVisitor.RequiresClientEval = requiresClientEval;
                        //querySqlGeneratorFunc = ()
                        //    => selectExpression.CreateFromSqlQuerySqlGenerator(
                        //        fromSqlAnnotation.Sql,
                        //        fromSqlAnnotation.Arguments);
                    }

                    var shaper = CreateShaper(elementType, entityType, selectExpression);

                    return(Expression.Call(
                               QueryModelVisitor.QueryCompilationContext.QueryMethodProvider // TODO: Don't use ShapedQuery when projecting
                               .ShapedQueryMethod
                               .MakeGenericMethod(shaper.Type),
                               EntityQueryModelVisitor.QueryContextParameter,
                               Expression.Constant(_shaperCommandContextFactory.Create(querySqlGeneratorFunc)),
                               Expression.Constant(shaper)));

                    //var member = valueFromOpenJsonAnnotation.Arguments as MemberExpression;
                    //if (member.Type == typeof(string))
                    //{



                    //    var m = this.VisitMember(member);
                    //}
                }
            }

            return(base.VisitEntityQueryable(elementType));
        }