public virtual Expression Translate(InMemoryQueryExpression queryExpression, Expression expression) { _queryExpression = queryExpression; _clientEval = false; _projectionMembers.Push(new ProjectionMember()); var result = Visit(expression); if (result == null) { _clientEval = true; result = Visit(expression); _projectionMapping.Clear(); } _queryExpression.ReplaceProjectionMapping(_projectionMapping); _queryExpression = null; _projectionMapping.Clear(); _projectionMembers.Clear(); return(result); }
public virtual Expression Translate(InMemoryQueryExpression queryExpression, Expression expression) { _queryExpression = queryExpression; _clientEval = false; _projectionMembers.Push(new ProjectionMember()); var expandedExpression = _queryableMethodTranslatingExpressionVisitor.ExpandWeakEntities(_queryExpression, expression); var result = Visit(expandedExpression); if (result == null) { _clientEval = true; expandedExpression = _queryableMethodTranslatingExpressionVisitor.ExpandWeakEntities(_queryExpression, expression); result = Visit(expandedExpression); _projectionMapping.Clear(); } _queryExpression.ReplaceProjectionMapping(_projectionMapping); _queryExpression = null; _projectionMapping.Clear(); _projectionMembers.Clear(); return(result); }
public virtual Expression Translate([NotNull] InMemoryQueryExpression queryExpression, [NotNull] Expression expression) { _queryExpression = queryExpression; _clientEval = false; _projectionMembers.Push(new ProjectionMember()); var expandedExpression = _queryableMethodTranslatingExpressionVisitor.ExpandWeakEntities(_queryExpression, expression); var result = Visit(expandedExpression); if (result == QueryCompilationContext.NotTranslatedExpression) { _clientEval = true; expandedExpression = _queryableMethodTranslatingExpressionVisitor.ExpandWeakEntities(_queryExpression, expression); result = Visit(expandedExpression); _projectionMapping.Clear(); } _queryExpression.ReplaceProjectionMapping(_projectionMapping); _queryExpression = null !; _projectionMapping.Clear(); _projectionMembers.Clear(); result = MatchTypes(result !, expression.Type); return(result); }
public override Expression?Visit(Expression?expression) { if (expression is InMemoryQueryExpression inMemoryQueryExpression) { var clonedInMemoryQueryExpression = new InMemoryQueryExpression( inMemoryQueryExpression.ServerQueryExpression, inMemoryQueryExpression._valueBufferParameter) { _groupingParameter = inMemoryQueryExpression._groupingParameter, _singleResultMethodInfo = inMemoryQueryExpression._singleResultMethodInfo, _scalarServerQuery = inMemoryQueryExpression._scalarServerQuery }; clonedInMemoryQueryExpression._clientProjections.AddRange(inMemoryQueryExpression._clientProjections.Select(e => Visit(e))); clonedInMemoryQueryExpression._projectionMappingExpressions.AddRange(inMemoryQueryExpression._projectionMappingExpressions); foreach (var item in inMemoryQueryExpression._projectionMapping) { clonedInMemoryQueryExpression._projectionMapping[item.Key] = Visit(item.Value); } return(clonedInMemoryQueryExpression); } if (expression is EntityProjectionExpression entityProjectionExpression) { return(entityProjectionExpression.Clone()); } return(base.Visit(expression)); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public ShaperExpressionProcessingExpressionVisitor( [CanBeNull] InMemoryQueryExpression queryExpression, [NotNull] ParameterExpression valueBufferParameter) { _queryExpression = queryExpression; _valueBufferParameter = valueBufferParameter; }
public InMemoryProjectionBindingExpressionVisitor( [NotNull] InMemoryQueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor, [NotNull] InMemoryExpressionTranslatingExpressionVisitor expressionTranslatingExpressionVisitor) { _queryableMethodTranslatingExpressionVisitor = queryableMethodTranslatingExpressionVisitor; _expressionTranslatingExpressionVisitor = expressionTranslatingExpressionVisitor; _queryExpression = null !; }
private object GetProjectionIndex(InMemoryQueryExpression queryExpression, ProjectionBindingExpression projectionBindingExpression) { return(projectionBindingExpression.ProjectionMember != null ? ((ConstantExpression)queryExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember)).Value : (projectionBindingExpression.Index != null ? (object)projectionBindingExpression.Index : projectionBindingExpression.IndexMap)); }
private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType entityType) { var queryExpression = new InMemoryQueryExpression(entityType); return(new ShapedQueryExpression( queryExpression, new EntityShaperExpression( entityType, new ProjectionBindingExpression( queryExpression, new ProjectionMember(), typeof(ValueBuffer)), false))); }
protected override ShapedQueryExpression CreateShapedQueryExpression(Type elementType) { var entityType = _model.FindEntityType(elementType); var queryExpression = new InMemoryQueryExpression(entityType); return(new ShapedQueryExpression( queryExpression, new EntityShaperExpression( entityType, new ProjectionBindingExpression( queryExpression, new ProjectionMember(), typeof(ValueBuffer)), false))); }
public InMemoryProjectionBindingRemovingExpressionVisitor(InMemoryQueryExpression queryExpression) { _queryExpression = queryExpression; }
public virtual void AddCrossJoin(InMemoryQueryExpression innerQueryExpression, Type transparentIdentifierType) { var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(ValueBuffer), "inner"); var resultValueBufferExpressions = new List <Expression>(); var projectionMapping = new Dictionary <ProjectionMember, Expression>(); var replacingVisitor = new ReplacingExpressionVisitor( new Dictionary <Expression, Expression> { { ValueBufferParameter, outerParameter }, { innerQueryExpression.ValueBufferParameter, innerParameter } }); var index = 0; var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); foreach (var projection in _projectionMapping) { if (projection.Value is EntityProjectionExpression entityProjection) { var readExpressionMap = new Dictionary <IProperty, Expression>(); foreach (var property in GetAllPropertiesInHierarchy(entityProjection.EntityType)) { resultValueBufferExpressions.Add(replacingVisitor.Visit(entityProjection.BindProperty(property))); readExpressionMap[property] = CreateReadValueExpression(property.ClrType, index++, property); } projectionMapping[projection.Key.Prepend(outerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else { resultValueBufferExpressions.Add(replacingVisitor.Visit(projection.Value)); projectionMapping[projection.Key.Prepend(outerMemberInfo)] = CreateReadValueExpression(projection.Value.Type, index++, InferPropertyFromInner(projection.Value)); } } var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); foreach (var projection in innerQueryExpression._projectionMapping) { if (projection.Value is EntityProjectionExpression entityProjection) { var readExpressionMap = new Dictionary <IProperty, Expression>(); foreach (var property in GetAllPropertiesInHierarchy(entityProjection.EntityType)) { resultValueBufferExpressions.Add(replacingVisitor.Visit(entityProjection.BindProperty(property))); readExpressionMap[property] = CreateReadValueExpression(property.ClrType, index++, property); } projectionMapping[projection.Key.Prepend(innerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else { resultValueBufferExpressions.Add(replacingVisitor.Visit(projection.Value)); projectionMapping[projection.Key.Prepend(innerMemberInfo)] = CreateReadValueExpression(projection.Value.Type, index++, InferPropertyFromInner(projection.Value)); } } var resultSelector = Lambda( New( _valueBufferConstructor, NewArrayInit( typeof(object), resultValueBufferExpressions .Select(e => e.Type.IsValueType ? Convert(e, typeof(object)) : e) .ToArray())), outerParameter, innerParameter); ServerQueryExpression = Call( InMemoryLinqOperatorProvider.SelectMany.MakeGenericMethod( typeof(ValueBuffer), typeof(ValueBuffer), typeof(ValueBuffer)), ServerQueryExpression, Lambda(innerQueryExpression.ServerQueryExpression, ValueBufferParameter), resultSelector); _projectionMapping = projectionMapping; }
public virtual void AddLeftJoin( InMemoryQueryExpression innerQueryExpression, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, Type transparentIdentifierType) { // GroupJoin phase var groupTransparentIdentifierType = TransparentIdentifierFactory.Create( typeof(ValueBuffer), typeof(IEnumerable <ValueBuffer>)); var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(IEnumerable <ValueBuffer>), "inner"); var outerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); var innerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); var resultSelector = Lambda( New( groupTransparentIdentifierType.GetTypeInfo().DeclaredConstructors.Single(), new[] { outerParameter, innerParameter }, new[] { outerMemberInfo, innerMemberInfo }), outerParameter, innerParameter); var groupJoinExpression = Call( InMemoryLinqOperatorProvider.GroupJoin.MakeGenericMethod( typeof(ValueBuffer), typeof(ValueBuffer), outerKeySelector.ReturnType, groupTransparentIdentifierType), ServerQueryExpression, innerQueryExpression.ServerQueryExpression, outerKeySelector, innerKeySelector, resultSelector); // SelectMany phase var collectionParameter = Parameter(groupTransparentIdentifierType, "collection"); var collection = MakeMemberAccess(collectionParameter, innerMemberInfo); outerParameter = Parameter(groupTransparentIdentifierType, "outer"); innerParameter = Parameter(typeof(ValueBuffer), "inner"); var resultValueBufferExpressions = new List <Expression>(); var projectionMapping = new Dictionary <ProjectionMember, Expression>(); var replacingVisitor = new ReplacingExpressionVisitor( new Dictionary <Expression, Expression> { { ValueBufferParameter, MakeMemberAccess(outerParameter, outerMemberInfo) }, { innerQueryExpression.ValueBufferParameter, innerParameter } }); var index = 0; outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); foreach (var projection in _projectionMapping) { if (projection.Value is EntityProjectionExpression entityProjection) { var readExpressionMap = new Dictionary <IProperty, Expression>(); foreach (var property in GetAllPropertiesInHierarchy(entityProjection.EntityType)) { var replacedExpression = replacingVisitor.Visit(entityProjection.BindProperty(property)); resultValueBufferExpressions.Add(replacedExpression); readExpressionMap[property] = CreateReadValueExpression(replacedExpression.Type, index++, property); } projectionMapping[projection.Key.Prepend(outerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else { var replacedExpression = replacingVisitor.Visit(projection.Value); resultValueBufferExpressions.Add(replacedExpression); projectionMapping[projection.Key.Prepend(outerMemberInfo)] = CreateReadValueExpression(replacedExpression.Type, index++, InferPropertyFromInner(projection.Value)); } } var outerIndex = index; innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); var nullableReadValueExpressionVisitor = new NullableReadValueExpressionVisitor(); foreach (var projection in innerQueryExpression._projectionMapping) { if (projection.Value is EntityProjectionExpression entityProjection) { var readExpressionMap = new Dictionary <IProperty, Expression>(); foreach (var property in GetAllPropertiesInHierarchy(entityProjection.EntityType)) { var replacedExpression = replacingVisitor.Visit(entityProjection.BindProperty(property)); replacedExpression = nullableReadValueExpressionVisitor.Visit(replacedExpression); resultValueBufferExpressions.Add(replacedExpression); readExpressionMap[property] = CreateReadValueExpression(replacedExpression.Type, index++, property); } projectionMapping[projection.Key.Prepend(innerMemberInfo)] = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); } else { var replacedExpression = replacingVisitor.Visit(projection.Value); replacedExpression = nullableReadValueExpressionVisitor.Visit(replacedExpression); resultValueBufferExpressions.Add(replacedExpression); projectionMapping[projection.Key.Prepend(innerMemberInfo)] = CreateReadValueExpression(replacedExpression.Type, index++, InferPropertyFromInner(projection.Value)); } } var collectionSelector = Lambda( Call( InMemoryLinqOperatorProvider.DefaultIfEmptyWithArg.MakeGenericMethod(typeof(ValueBuffer)), collection, New( _valueBufferConstructor, NewArrayInit( typeof(object), Enumerable.Range(0, index - outerIndex).Select(i => Constant(null))))), collectionParameter); resultSelector = Lambda( New( _valueBufferConstructor, NewArrayInit( typeof(object), resultValueBufferExpressions .Select(e => e.Type.IsValueType ? Convert(e, typeof(object)) : e) .ToArray())), outerParameter, innerParameter); ServerQueryExpression = Call( InMemoryLinqOperatorProvider.SelectMany.MakeGenericMethod( groupTransparentIdentifierType, typeof(ValueBuffer), typeof(ValueBuffer)), groupJoinExpression, collectionSelector, resultSelector); _projectionMapping = projectionMapping; }
public ShaperExpressionProcessingExpressionVisitor( InMemoryQueryExpression queryExpression) { _queryExpression = queryExpression; }
public virtual EntityShaperExpression AddNavigationToWeakEntityType( EntityProjectionExpression entityProjectionExpression, INavigation navigation, InMemoryQueryExpression innerQueryExpression, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector) { // GroupJoin phase var groupTransparentIdentifierType = TransparentIdentifierFactory.Create( typeof(ValueBuffer), typeof(IEnumerable <ValueBuffer>)); var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(IEnumerable <ValueBuffer>), "inner"); var outerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); var innerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); var resultSelector = Lambda( New( groupTransparentIdentifierType.GetTypeInfo().DeclaredConstructors.Single(), new[] { outerParameter, innerParameter }, new[] { outerMemberInfo, innerMemberInfo }), outerParameter, innerParameter); var groupJoinExpression = Call( InMemoryLinqOperatorProvider.GroupJoin.MakeGenericMethod( typeof(ValueBuffer), typeof(ValueBuffer), outerKeySelector.ReturnType, groupTransparentIdentifierType), ServerQueryExpression, innerQueryExpression.ServerQueryExpression, outerKeySelector, innerKeySelector, resultSelector); // SelectMany phase var collectionParameter = Parameter(groupTransparentIdentifierType, "collection"); var collection = MakeMemberAccess(collectionParameter, innerMemberInfo); outerParameter = Parameter(groupTransparentIdentifierType, "outer"); innerParameter = Parameter(typeof(ValueBuffer), "inner"); var resultValueBufferExpressions = new List <Expression>(); var projectionMapping = new Dictionary <ProjectionMember, Expression>(); var replacingVisitor = new ReplacingExpressionVisitor( new Dictionary <Expression, Expression> { { CurrentParameter, MakeMemberAccess(outerParameter, outerMemberInfo) }, { innerQueryExpression.CurrentParameter, innerParameter } }); var index = 0; EntityProjectionExpression copyEntityProjectionToOuter(EntityProjectionExpression entityProjection) { var readExpressionMap = new Dictionary <IProperty, Expression>(); foreach (var property in GetAllPropertiesInHierarchy(entityProjection.EntityType)) { var replacedExpression = replacingVisitor.Visit(entityProjection.BindProperty(property)); resultValueBufferExpressions.Add(replacedExpression); readExpressionMap[property] = CreateReadValueExpression(replacedExpression.Type, index++, property); } var newEntityProjection = new EntityProjectionExpression(entityProjection.EntityType, readExpressionMap); if (ReferenceEquals(entityProjectionExpression, entityProjection)) { entityProjectionExpression = newEntityProjection; } // Also lift nested entity projections foreach (var navigation in entityProjection.EntityType.GetTypesInHierarchy() .SelectMany(EntityTypeExtensions.GetDeclaredNavigations)) { var boundEntityShaperExpression = entityProjection.BindNavigation(navigation); if (boundEntityShaperExpression != null) { var innerEntityProjection = (EntityProjectionExpression)boundEntityShaperExpression.ValueBufferExpression; var newInnerEntityProjection = copyEntityProjectionToOuter(innerEntityProjection); boundEntityShaperExpression = boundEntityShaperExpression.Update(newInnerEntityProjection); newEntityProjection.AddNavigationBinding(navigation, boundEntityShaperExpression); } } return(newEntityProjection); } foreach (var projection in _projectionMapping) { if (projection.Value is EntityProjectionExpression entityProjection) { projectionMapping[projection.Key] = copyEntityProjectionToOuter(entityProjection); } else { var replacedExpression = replacingVisitor.Visit(projection.Value); resultValueBufferExpressions.Add(replacedExpression); projectionMapping[projection.Key] = CreateReadValueExpression(replacedExpression.Type, index++, InferPropertyFromInner(projection.Value)); } } _projectionMapping = projectionMapping; var outerIndex = index; var nullableReadValueExpressionVisitor = new NullableReadValueExpressionVisitor(); var innerEntityProjection = (EntityProjectionExpression)innerQueryExpression.GetMappedProjection(new ProjectionMember()); var innerReadExpressionMap = new Dictionary <IProperty, Expression>(); foreach (var property in GetAllPropertiesInHierarchy(innerEntityProjection.EntityType)) { var replacedExpression = replacingVisitor.Visit(innerEntityProjection.BindProperty(property)); replacedExpression = nullableReadValueExpressionVisitor.Visit(replacedExpression); resultValueBufferExpressions.Add(replacedExpression); innerReadExpressionMap[property] = CreateReadValueExpression(replacedExpression.Type, index++, property); } innerEntityProjection = new EntityProjectionExpression(innerEntityProjection.EntityType, innerReadExpressionMap); var collectionSelector = Lambda( Call( InMemoryLinqOperatorProvider.DefaultIfEmptyWithArgument.MakeGenericMethod(typeof(ValueBuffer)), collection, New( _valueBufferConstructor, NewArrayInit( typeof(object), Enumerable.Range(0, index - outerIndex).Select(i => Constant(null))))), collectionParameter); resultSelector = Lambda( New( _valueBufferConstructor, NewArrayInit( typeof(object), resultValueBufferExpressions .Select(e => e.Type.IsValueType ? Convert(e, typeof(object)) : e) .ToArray())), outerParameter, innerParameter); ServerQueryExpression = Call( InMemoryLinqOperatorProvider.SelectManyWithCollectionSelector.MakeGenericMethod( groupTransparentIdentifierType, typeof(ValueBuffer), typeof(ValueBuffer)), groupJoinExpression, collectionSelector, resultSelector); var entityShaper = new EntityShaperExpression(innerEntityProjection.EntityType, innerEntityProjection, nullable: true); entityProjectionExpression.AddNavigationBinding(navigation, entityShaper); return(entityShaper); }