public virtual Expression Translate(HarmonyQueryExpression 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); }
private object GetProjectionIndex( HarmonyQueryExpression queryExpression, ProjectionBindingExpression projectionBindingExpression) { return(projectionBindingExpression.ProjectionMember != null ? ((ConstantExpression)queryExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember)).Value : (projectionBindingExpression.Index != null ? (object)projectionBindingExpression.Index : projectionBindingExpression.IndexMap)); }
public HarmonyTableExpression(IEntityType entityType, string name, HarmonyQueryExpression rootExpr) { EntityType = entityType; Type = typeof(IEnumerable <>).MakeGenericType(new Type[] { EntityType.ClrType }); Name = name; RootExpression = rootExpr; WhereExpressions = new List <Expression>(); OrderByExpressions = new List <Tuple <Expression, bool> >(); OnExpressions = new List <Expression>(); Aliases = new List <Expression>(); }
public virtual void AddLeftJoin( HarmonyQueryExpression innerQueryExpression, Expression outerKeySelector, Expression innerKeySelector) { var serverQueryExpression = innerQueryExpression.FindServerExpression(); if (!RootExpressions.ContainsKey(innerQueryExpression.CurrentParameter)) { RootExpressions.Add(innerQueryExpression.CurrentParameter, serverQueryExpression); } serverQueryExpression.OnExpressions.Add(Expression.Equal(innerKeySelector, outerKeySelector)); }
public ShaperExpressionProcessingExpressionVisitor( HarmonyQueryExpression queryExpression, ParameterExpression valueBufferParameter) { _queryExpression = queryExpression; _valueBufferParameter = valueBufferParameter; }
public virtual EntityShaperExpression AddNavigationToWeakEntityType( EntityProjectionExpression entityProjectionExpression, INavigation navigation, HarmonyQueryExpression innerQueryExpression, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector) { // GroupJoin phase var groupTransparentIdentifierType = TransparentIdentifierFactory.Create( typeof(DataObjectBase), typeof(IEnumerable <DataObjectBase>)); var outerParameter = Parameter(typeof(DataObjectBase), "outer"); var innerParameter = Parameter(typeof(IEnumerable <DataObjectBase>), "inner"); var outerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); var innerMemberInfo = groupTransparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); var resultSelector = Lambda( New( groupTransparentIdentifierType.GetTypeInfo().DeclaredConstructors.Single(), new[] { outerParameter, innerParameter }, outerMemberInfo, innerMemberInfo), outerParameter, innerParameter); var groupJoinExpression = Call( EnumerableMethods.GroupJoin.MakeGenericMethod( typeof(DataObjectBase), typeof(DataObjectBase), 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(DataObjectBase), "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(Microsoft.EntityFrameworkCore.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( // EnumerableMethods.DefaultIfEmptyWithArgument.MakeGenericMethod(typeof(DataObjectBase)), // 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( // EnumerableMethods.SelectManyWithCollectionSelector.MakeGenericMethod( // groupTransparentIdentifierType, typeof(DataObjectBase), typeof(DataObjectBase)), // groupJoinExpression, // collectionSelector, // resultSelector); throw new NotImplementedException(); var entityShaper = new EntityShaperExpression(innerEntityProjection.EntityType, innerEntityProjection, nullable: true); entityProjectionExpression.AddNavigationBinding(navigation, entityShaper); return(entityShaper); }
public virtual void AddSelectMany(HarmonyQueryExpression innerQueryExpression, Type transparentIdentifierType, bool innerNullable) { var outerParameter = Parameter(typeof(DataObjectBase), "outer"); var innerParameter = Parameter(typeof(DataObjectBase), "inner"); var resultValueBufferExpressions = new List <Expression>(); var projectionMapping = new Dictionary <ProjectionMember, Expression>(); var replacingVisitor = new ReplacingExpressionVisitor( new Dictionary <Expression, Expression> { { CurrentParameter, outerParameter }, { innerQueryExpression.CurrentParameter, 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)) { 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 { 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"); 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)); if (innerNullable) { 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); if (innerNullable) { replacedExpression = nullableReadValueExpressionVisitor.Visit(replacedExpression); } resultValueBufferExpressions.Add(replacedExpression); projectionMapping[projection.Key.Prepend(innerMemberInfo)] = CreateReadValueExpression(replacedExpression.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( // EnumerableMethods.SelectManyWithCollectionSelector.MakeGenericMethod( // typeof(DataObjectBase), typeof(DataObjectBase), typeof(DataObjectBase)), // ServerQueryExpression, // Lambda(innerQueryExpression.ServerQueryExpression, CurrentParameter), // resultSelector); throw new NotImplementedException(); _projectionMapping = projectionMapping; }