/// <summary> /// Parses the passes query parameters to a <see cref="ModelFilter{T}" />. /// </summary> /// <param name="queryParameters"></param> /// <returns></returns> public IModelFilter <T> Parse(NameValueCollection queryParameters) { var orderbyField = queryParameters[StringConstants.OrderByParameter]; var selects = queryParameters[StringConstants.SelectParameter]; var filter = queryParameters[StringConstants.FilterParameter]; var skip = queryParameters[StringConstants.SkipParameter]; var top = queryParameters[StringConstants.TopParameter]; var inlineCount = queryParameters[StringConstants.InlineCount]; var includeCount = !string.IsNullOrWhiteSpace(inlineCount) || inlineCount == "allpages"; var filterExpression = _filterExpressionFactory.Create <T>(filter); var sortDescriptions = _sortExpressionFactory.Create <T>(orderbyField); var selectFunction = _selectExpressionFactory.Create(selects); return(new ModelFilter <T>(filterExpression, selectFunction, sortDescriptions, string.IsNullOrWhiteSpace(skip) ? -1 : Convert.ToInt32(skip), string.IsNullOrWhiteSpace(top) ? -1 : Convert.ToInt32(top), includeCount)); }
/// <summary> /// Parses the passes query parameters to a <see cref="ModelFilter{T}"/>. /// </summary> /// <param name="queryParameters"></param> /// <returns></returns> public IModelFilter <T> Parse(NameValueCollection queryParameters) { var orderbyField = queryParameters[StringConstants.OrderByParameter]; var selects = queryParameters[StringConstants.SelectParameter]; var filter = queryParameters[StringConstants.FilterParameter]; var skip = queryParameters[StringConstants.SkipParameter]; var top = queryParameters[StringConstants.TopParameter]; var filterExpression = m_filterExpressionFactory.Create <T>(filter); var sortDescriptions = m_sortExpressionFactory.Create <T>(orderbyField); var selectFunction = m_selectExpressionFactory.Create(selects); var modelFilter = new ModelFilter <T>( filterExpression, selectFunction, sortDescriptions, skip.IsNullOrWhiteSpace() ? -1 : Convert.ToInt32(skip), top.IsNullOrWhiteSpace() ? -1 : Convert.ToInt32(top)); return(modelFilter); }
/// <summary> /// Parses the passes query parameters to a <see cref="ModelFilter{T}"/>. /// </summary> /// <param name="queryParameters"></param> /// <returns></returns> public IModelFilter <T> Parse(IEnumerable <KeyValuePair <string, string> > queryParameters) { var orderbyField = queryParameters.GetValue(StringConstants.OrderByParameter).FirstOrDefault(); var selects = queryParameters.GetValue(StringConstants.SelectParameter).FirstOrDefault(); var filter = queryParameters.GetValue(StringConstants.FilterParameter).FirstOrDefault(); var skip = queryParameters.GetValue(StringConstants.SkipParameter).FirstOrDefault(); var top = queryParameters.GetValue(StringConstants.TopParameter).FirstOrDefault(); var filterExpression = _filterExpressionFactory.Create <T>(filter); var sortDescriptions = _sortExpressionFactory.Create <T>(orderbyField); var selectFunction = _selectExpressionFactory.Create(selects); var modelFilter = new ModelFilter <T>( _settings, filterExpression, selectFunction, sortDescriptions, string.IsNullOrWhiteSpace(skip) ? -1 : Convert.ToInt32(skip), string.IsNullOrWhiteSpace(top) ? -1 : Convert.ToInt32(top)); return(modelFilter); }
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); }
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))); }
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))); } } }
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)); }
protected override Expression VisitEntityQueryable(Type elementType) { Check.NotNull(elementType, nameof(elementType)); var queryMethodInfo = CreateValueBufferMethodInfo; var relationalQueryCompilationContext = QueryModelVisitor.QueryCompilationContext; var entityType = _model.FindEntityType(elementType); var selectExpression = _selectExpressionFactory.Create(); var name = _relationalAnnotationProvider.For(entityType).TableName; var tableAlias = _querySource.HasGeneratedItemName() ? name[0].ToString().ToLowerInvariant() : _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, _relationalAnnotationProvider.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(RelationalStrings.StoredProcedureIncludeNotSupported); } QueryModelVisitor.RequiresClientEval = true; composable = false; } if (fromSqlAnnotation.QueryModel.IsIdentityQuery() && !fromSqlAnnotation.QueryModel.ResultOperators.Any()) { composable = false; } } QueryModelVisitor.AddQuery(_querySource, selectExpression); var queryMethodArguments = new List <Expression> { Expression.Constant(_querySource), _valueBufferParameter, Expression.Constant(0) }; if (QueryModelVisitor.QueryCompilationContext .QuerySourceRequiresMaterialization(_querySource) || QueryModelVisitor.RequiresClientEval) { var materializer = _materializerFactory .CreateMaterializer( entityType, selectExpression, (p, se) => se.AddToProjection( _relationalAnnotationProvider.For(p).ColumnName, p, _querySource), _querySource); queryMethodInfo = CreateEntityMethodInfo.MakeGenericMethod(elementType); queryMethodArguments.AddRange( new[] { EntityQueryModelVisitor.QueryContextParameter, Expression.Constant(entityType), Expression.Constant(QueryModelVisitor.QueryCompilationContext.IsTrackingQuery), Expression.Constant(_keyValueFactorySource.GetKeyFactory(entityType.FindPrimaryKey())), materializer, Expression.Constant(false), Expression.Constant(QueryModelVisitor.QueryCompilationContext.IsQueryBufferRequired) }); } Func <ISqlQueryGenerator> sqlQueryGeneratorFunc; if (composable) { sqlQueryGeneratorFunc = selectExpression.CreateGenerator; } else { sqlQueryGeneratorFunc = () => selectExpression.CreateRawCommandGenerator( sqlString, sqlParameters); } return(Expression.Call( QueryModelVisitor.QueryCompilationContext.QueryMethodProvider // TODO: Don't use ShapedQuery when projecting .ShapedQueryMethod .MakeGenericMethod(queryMethodInfo.ReturnType), EntityQueryModelVisitor.QueryContextParameter, Expression.Constant(_commandBuilderFactory.Create(sqlQueryGeneratorFunc)), Expression.Lambda( Expression.Call(queryMethodInfo, queryMethodArguments), _valueBufferParameter))); }