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));
        }
Ejemplo n.º 5
0
 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;
        }