Example #1
0
            protected override Expression VisitEntityQueryable(Type elementType)
            {
                var relationalQueryCompilationContext
                    = ((RelationalQueryCompilationContext)QueryModelVisitor.QueryCompilationContext);

                var queryMethodInfo = CreateValueReaderMethodInfo;
                var entityType      = QueryModelVisitor.QueryCompilationContext.Model.GetEntityType(elementType);

                var selectExpression = new SelectExpression();
                var tableName        = entityType.TableName();

                selectExpression
                .AddTable(
                    new TableExpression(
                        tableName,
                        entityType.Schema(),
                        _querySource.ItemName.StartsWith("<generated>_")
                                ? tableName.First().ToString().ToLower()
                                : _querySource.ItemName,
                        _querySource));

                QueryModelVisitor._queriesBySource.Add(_querySource, selectExpression);

                var queryMethodArguments
                    = new List <Expression>
                    {
                    Expression.Constant(_querySource),
                    QueryContextParameter,
                    QuerySourceScopeParameter,
                    _readerParameter
                    };

                if (QueryModelVisitor.QuerySourceRequiresMaterialization(_querySource))
                {
                    foreach (var property in entityType.Properties)
                    {
                        selectExpression.AddToProjection(property, _querySource);
                    }

                    queryMethodInfo = CreateEntityMethodInfo.MakeGenericMethod(elementType);

                    queryMethodArguments.Add(Expression.Constant(0));
                    queryMethodArguments.Add(Expression.Constant(entityType));
                }

                return(Expression.Call(
                           relationalQueryCompilationContext.QueryMethodProvider.QueryMethod
                           .MakeGenericMethod(queryMethodInfo.ReturnType),
                           QueryContextParameter,
                           Expression.Constant(new CommandBuilder(selectExpression, relationalQueryCompilationContext)),
                           Expression.Lambda(
                               Expression.Call(queryMethodInfo, queryMethodArguments),
                               _readerParameter)));
            }
Example #2
0
        protected override Expression VisitEntityQueryable(Type elementType)
        {
            Check.NotNull(elementType, nameof(elementType));

            var queryMethodInfo = CreateValueBufferMethodInfo;
            var relationalQueryCompilationContext = QueryModelVisitor.QueryCompilationContext;
            var entityType       = relationalQueryCompilationContext.Model.GetEntityType(elementType);
            var selectExpression = new SelectExpression();
            var name             = relationalQueryCompilationContext.RelationalExtensions.For(entityType).TableName;

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

            var fromSqlAnnotation
                = relationalQueryCompilationContext
                  .GetCustomQueryAnnotations(RelationalQueryableExtensions.FromSqlMethodInfo)
                  .LastOrDefault(a => a.QuerySource == _querySource);

            var composable = true;
            var sqlString  = "";

            object[] sqlParameters = null;

            if (fromSqlAnnotation == null)
            {
                selectExpression.AddTable(
                    new TableExpression(
                        name,
                        relationalQueryCompilationContext.RelationalExtensions.For(entityType).Schema,
                        tableAlias,
                        _querySource));
            }
            else
            {
                sqlString     = (string)fromSqlAnnotation.Arguments[1];
                sqlParameters = (object[])fromSqlAnnotation.Arguments[2];

                selectExpression.AddTable(
                    new RawSqlDerivedTableExpression(
                        sqlString,
                        sqlParameters,
                        tableAlias,
                        _querySource));

                var sqlStart = sqlString.SkipWhile(char.IsWhiteSpace).Take(7).ToArray();

                if (sqlStart.Length != 7 ||
                    !char.IsWhiteSpace(sqlStart.Last()) ||
                    !new string(sqlStart).StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
                {
                    if (relationalQueryCompilationContext.QueryAnnotations
                        .OfType <IncludeQueryAnnotation>().Any())
                    {
                        throw new InvalidOperationException(Strings.StoredProcedureIncludeNotSupported);
                    }

                    QueryModelVisitor.RequiresClientEval = true;

                    composable = false;
                }

                if (!fromSqlAnnotation.QueryModel.BodyClauses.Any() &&
                    !fromSqlAnnotation.QueryModel.ResultOperators.Any())
                {
                    composable = false;
                }
            }

            QueryModelVisitor.AddQuery(_querySource, selectExpression);

            var queryMethodArguments
                = new List <Expression>
                {
                Expression.Constant(_querySource),
                EntityQueryModelVisitor.QueryContextParameter,
                EntityQueryModelVisitor.QueryResultScopeParameter,
                _valueBufferParameter,
                Expression.Constant(0)
                };

            if (QueryModelVisitor.QueryCompilationContext
                .QuerySourceRequiresMaterialization(_querySource) ||
                QueryModelVisitor.RequiresClientEval)
            {
                var materializer
                    = new MaterializerFactory(
                          relationalQueryCompilationContext
                          .EntityMaterializerSource)
                      .CreateMaterializer(
                          entityType,
                          selectExpression,
                          (p, se) =>
                          se.AddToProjection(
                              relationalQueryCompilationContext.RelationalExtensions.For(p).ColumnName,
                              p,
                              _querySource),
                          QueryModelVisitor.QueryCompilationContext.RelationalExtensions,
                          _querySource);

                queryMethodInfo
                    = CreateEntityMethodInfo.MakeGenericMethod(elementType);

                var keyFactory
                    = relationalQueryCompilationContext.EntityKeyFactorySource
                      .GetKeyFactory(entityType.GetPrimaryKey());

                queryMethodArguments.AddRange(
                    new[]
                {
                    Expression.Constant(entityType),
                    Expression.Constant(QueryModelVisitor.QuerySourceRequiresTracking(_querySource)),
                    Expression.Constant(keyFactory),
                    Expression.Constant(entityType.GetPrimaryKey().Properties),
                    materializer
                });
            }

            Func <ISqlQueryGenerator> sqlQueryGeneratorFactory;

            if (composable)
            {
                sqlQueryGeneratorFactory = () =>
                                           relationalQueryCompilationContext.CreateSqlQueryGenerator(selectExpression);
            }
            else
            {
                sqlQueryGeneratorFactory = () =>
                                           new RawSqlQueryGenerator(selectExpression, sqlString, sqlParameters, relationalQueryCompilationContext.TypeMapper);
            }

            return(Expression.Call(
                       relationalQueryCompilationContext.QueryMethodProvider.ShapedQueryMethod
                       .MakeGenericMethod(queryMethodInfo.ReturnType),
                       EntityQueryModelVisitor.QueryContextParameter,
                       Expression.Constant(
                           new CommandBuilder(
                               sqlQueryGeneratorFactory,
                               relationalQueryCompilationContext.ValueBufferFactoryFactory)),
                       Expression.Lambda(
                           Expression.Call(queryMethodInfo, queryMethodArguments),
                           _valueBufferParameter)));
        }