protected override ShapedQueryExpression TranslateAll(ShapedQueryExpression source, LambdaExpression predicate)
        {
            var selectExpression = (SelectExpression)source.QueryExpression;

            if (selectExpression.Limit != null ||
                selectExpression.Offset != null)
            {
                selectExpression.PushdownIntoSubQuery();
            }

            var translation = TranslateLambdaExpression(source, predicate);

            if (translation != null)
            {
                selectExpression.ApplyPredicate(_sqlExpressionFactory.Not(translation));
                selectExpression.ReplaceProjection(new Dictionary <ProjectionMember, Expression>());
                if (selectExpression.Limit == null &&
                    selectExpression.Offset == null)
                {
                    selectExpression.ClearOrdering();
                }

                translation             = _sqlExpressionFactory.Exists(selectExpression, true);
                source.QueryExpression  = _sqlExpressionFactory.Select(translation);
                source.ShaperExpression = new ProjectionBindingExpression(source.QueryExpression, new ProjectionMember(), typeof(bool));

                return(source);
            }

            throw new InvalidOperationException();
        }
        protected override ShapedQueryExpression CreateShapedQueryExpression(Type elementType)
        {
            var entityType      = _model.FindEntityType(elementType);
            var queryExpression = _sqlExpressionFactory.Select(entityType);

            return(CreateShapedQueryExpression(entityType, queryExpression));
        }
        protected override ShapedQueryExpression CreateShapedQueryExpression(Type elementType)
        {
            Check.NotNull(elementType, nameof(elementType));

            var entityType       = _model.FindEntityType(elementType);
            var selectExpression = _sqlExpressionFactory.Select(entityType);

            return(new ShapedQueryExpression(
                       selectExpression,
                       new EntityShaperExpression(
                           entityType,
                           new ProjectionBindingExpression(
                               selectExpression,
                               new ProjectionMember(),
                               typeof(ValueBuffer)),
                           false)));
        }
Beispiel #4
0
            private Expression Expand(Expression source, MemberIdentity member)
            {
                Type convertedType = null;

                if (source is UnaryExpression unaryExpression &&
                    unaryExpression.NodeType == ExpressionType.Convert)
                {
                    source = unaryExpression.Operand;
                    if (unaryExpression.Type != typeof(object))
                    {
                        convertedType = unaryExpression.Type;
                    }
                }

                if (source is EntityShaperExpression entityShaperExpression)
                {
                    var entityType = entityShaperExpression.EntityType;
                    if (convertedType != null)
                    {
                        entityType = entityType.RootType().GetDerivedTypesInclusive()
                                     .FirstOrDefault(et => et.ClrType == convertedType);

                        if (entityType == null)
                        {
                            return(null);
                        }
                    }

                    var navigation = member.MemberInfo != null
                        ? entityType.FindNavigation(member.MemberInfo)
                        : entityType.FindNavigation(member.Name);

                    if (navigation != null &&
                        navigation.ForeignKey.IsOwnership)
                    {
                        if (navigation.IsCollection())
                        {
                            return(CreateShapedQueryExpression(
                                       navigation.GetTargetType(),
                                       _sqlExpressionFactory.Select(navigation.GetTargetType())));
                        }

                        var entityProjectionExpression = (EntityProjectionExpression)
                                                         (entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression
                                ? _selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember)
                                : entityShaperExpression.ValueBufferExpression);

                        var innerShaper = entityProjectionExpression.BindNavigation(navigation);
                        if (innerShaper == null)
                        {
                            var targetEntityType      = navigation.GetTargetType();
                            var innerSelectExpression = _sqlExpressionFactory.Select(targetEntityType);
                            var innerShapedQuery      = CreateShapedQueryExpression(targetEntityType, innerSelectExpression);

                            var makeNullable = navigation.ForeignKey.PrincipalKey.Properties
                                               .Concat(navigation.ForeignKey.Properties)
                                               .Select(p => p.ClrType)
                                               .Any(t => t.IsNullableType());

                            var outerKey = CreateKeyAccessExpression(
                                entityShaperExpression, navigation.ForeignKey.PrincipalKey.Properties, makeNullable);
                            var innerKey = CreateKeyAccessExpression(
                                innerShapedQuery.ShaperExpression, navigation.ForeignKey.Properties, makeNullable);

                            var joinPredicate = _sqlTranslator.Translate(Expression.Equal(outerKey, innerKey));
                            _selectExpression.AddLeftJoin(innerSelectExpression, joinPredicate, null);
                            var leftJoinTable = ((LeftJoinExpression)_selectExpression.Tables.Last()).Table;
                            innerShaper = new EntityShaperExpression(targetEntityType,
                                                                     new EntityProjectionExpression(targetEntityType, leftJoinTable, true),
                                                                     true);
                            entityProjectionExpression.AddNavigationBinding(navigation, innerShaper);
                        }

                        return(innerShaper);
                    }
                }

                return(null);
            }