示例#1
0
        Expression IQueryPolicy.ApplyPolicy(Expression expression, MemberInfo member)
        {
            List <LambdaExpression> ops;

            if (operations.TryGetValue(member, out ops))
            {
                var syntax = Database.Provider.GetService <ISyntaxProvider>();
                var result = expression;
                foreach (var fnOp in ops)
                {
                    var pop = PartialEvaluator.Eval(fnOp);
                    result = QueryBinder.Bind(Expression.Invoke(pop, result), syntax);
                }

                var projection = (ProjectionExpression)result;
                if (projection.Type != expression.Type)
                {
                    var fnAgg = QueryUtility.GetAggregator(expression.Type, projection.Type);
                    projection = new ProjectionExpression(projection.Select, projection.Projector, fnAgg);
                }

                return(projection);
            }

            return(expression);
        }
示例#2
0
        /// <summary>
        /// Apply mapping translations to this expression
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual Expression Translate(Expression expression)
        {
            // convert references to LINQ operators into query specific nodes
            expression = QueryBinder.Bind(this, expression);

            // move aggregate computations so they occur in same select as group-by
            expression = AggregateRewriter.Rewrite(this.Translator.Linguist.Language, expression);

            // do reduction so duplicate association's are likely to be clumped together
            expression = UnusedColumnRemover.Remove(expression);
            expression = RedundantColumnRemover.Remove(expression);
            expression = RedundantSubqueryRemover.Remove(expression);
            expression = RedundantJoinRemover.Remove(expression);

            // convert references to association properties into correlated queries
            var bound = RelationshipBinder.Bind(this, expression);

            if (bound != expression)
            {
                expression = bound;
                // clean up after ourselves! (multiple references to same association property)
                expression = RedundantColumnRemover.Remove(expression);
                expression = RedundantJoinRemover.Remove(expression);
            }

            // rewrite comparision checks between entities and multi-valued constructs
            expression = ComparisonRewriter.Rewrite(this.Mapping, expression);

            return(expression);
        }
示例#3
0
        private Expression TranslateInternal(Expression expression, TranslateOptions options)
        {
            var syntax      = TranslateScope.Current.Context.Database.Provider.GetService <ISyntaxProvider>();
            var translation = QueryBinder.Bind(expression, syntax);

            translation = LogicalDeleteFlagRewriter.Rewrite(translation);
            translation = GlobalQueryPolicyRewriter.Rewrite(translation);
            translation = AggregateRewriter.Rewrite(translation);
            translation = UnusedColumnRemover.Remove(translation);
            translation = RedundantColumnRemover.Remove(translation);
            translation = RedundantSubqueryRemover.Remove(translation);
            translation = RedundantJoinRemover.Remove(translation);

            var bound = RelationshipBinder.Bind(translation);

            if (bound != translation)
            {
                translation = bound;
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }
            translation = ComparisonRewriter.Rewrite(translation);

            var rewritten = RelationshipIncluder.Include(TranslateScope.Current.Context, translation);

            if (rewritten != translation)
            {
                translation = rewritten;
                translation = UnusedColumnRemover.Remove(translation);
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantSubqueryRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }

            rewritten = SingletonProjectionRewriter.Rewrite(translation);
            if (rewritten != translation)
            {
                translation = rewritten;
                translation = UnusedColumnRemover.Remove(translation);
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantSubqueryRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }

            rewritten = ClientJoinedProjectionRewriter.Rewrite(translation);
            if (rewritten != translation)
            {
                translation = rewritten;
                translation = UnusedColumnRemover.Remove(translation);
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantSubqueryRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }

            translation = BuildExpression(translation);

            return(translation);
        }
示例#4
0
 private ProjectionExpression Translate(Expression expression)
 {
     expression = Evaluator.PartialEval(expression, CanBeEvaluatedLocally);
     expression = QueryBinder.Bind(this, expression);
     expression = SubstringExpressionRewriter.Rewrite(expression);
     expression = SubstringEmptyClauseRemover.Rewrite(expression);
     expression = BinaryExpressionRewriter.Rewrite(expression);
     expression = AttributeComparisonReorderingRewriter.Rewrite(expression);
     expression = NullComparisonRewriter.Rewrite(expression);
     expression = AndOrExpressionCollector.Rewrite(expression);
     expression = RedundantExpressionRemover.Rewrite(expression);
     return((ProjectionExpression)expression);
 }
示例#5
0
        internal static Expression Bind(DataAccessModel dataAccessModel, SqlDataTypeProvider sqlDataTypeProvider, Expression expression)
        {
            var placeholderCount = -1;

            expression = Evaluator.PartialEval(expression, ref placeholderCount);
            expression = QueryBinder.Bind(dataAccessModel, expression);
            expression = SqlEnumTypeNormalizer.Normalize(expression, sqlDataTypeProvider.GetTypeForEnums());
            expression = Evaluator.PartialEval(expression, ref placeholderCount);
            expression = SqlNullComparisonCoalescer.Coalesce(expression);
            expression = SqlTupleOrAnonymousTypeComparisonExpander.Expand(expression);
            expression = SqlObjectOperandComparisonExpander.Expand(expression);
            expression = SqlRedundantFunctionCallRemover.Remove(expression);

            return(expression);
        }
 internal Expression Translate(Expression expression)
 {
     if (expression is ProjectionExpression projection)
     {
         return(projection);
     }
     expression = Evaluator.PartialEval(expression, CanBeEvaluatedLocally);
     expression = QueryBinder.Bind(this, expression);
     expression = ConstantEscaper.EscapeConstants(expression);
     expression = OrderByRewriter.Rewrite(expression);
     expression = RedundantSubqueryRemover.Remove(expression);
     expression = UnusedColumnRemover.Remove(expression);
     expression = AggregateSimplifier.Simplify(expression);
     return(expression);
 }
示例#7
0
        public override string GetQueryText(Expression expression)
        {
            SqlProjectionExpression projectionExpression;

            if (this.RelatedDataAccessObjectContext == null)
            {
                projectionExpression = (SqlProjectionExpression)(QueryBinder.Bind(this.DataAccessModel, expression, null, null));
            }
            else
            {
                projectionExpression = (SqlProjectionExpression)(QueryBinder.Bind(this.DataAccessModel, expression, this.RelatedDataAccessObjectContext.ElementType, this.RelatedDataAccessObjectContext.ExtraCondition));
            }

            var result = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(projectionExpression);

            return(result.CommandText);
        }
示例#8
0
        public virtual Expression Translate(Expression expression)
        {
            expression = QueryBinder.Bind(this, expression);
            expression = AggregateRewriter.Rewrite(this.Translator.Linguist.Language, expression);
            expression = UnusedColumnRemover.Remove(expression);
            expression = RedundantColumnRemover.Remove(expression);
            expression = RedundantSubqueryRemover.Remove(expression);
            expression = RedundantJoinRemover.Remove(expression);
            Expression expression2 = RelationshipBinder.Bind(this, expression);

            if (expression2 != expression)
            {
                expression = expression2;
                expression = RedundantColumnRemover.Remove(expression);
                expression = RedundantJoinRemover.Remove(expression);
            }
            expression = ComparisonRewriter.Rewrite(this.Mapping, expression);
            return(expression);
        }
示例#9
0
        public static void DeleteWhere <T>(this DataAccessObjectsQueryable <T> queryable, Expression <Func <T, bool> > condition)
            where T : DataAccessObject
        {
            queryable.DataAccessModel.Flush();

            var transactionContext = queryable.DataAccessModel.AmbientTransactionManager.GetCurrentContext(true);

            using (var acquisition = transactionContext.AcquirePersistenceTransactionContext(queryable.DataAccessModel.GetCurrentSqlDatabaseContext()))
            {
                var expression = (Expression)Expression.Call(null, MethodCache <T> .DeleteMethod, Expression.Constant(queryable, typeof(DataAccessObjectsQueryable <T>)), condition);

                expression = Evaluator.PartialEval(expression);
                expression = QueryBinder.Bind(queryable.DataAccessModel, expression, queryable.ElementType, queryable.ExtraCondition);
                expression = ObjectOperandComparisonExpander.Expand(expression);
                expression = SqlQueryProvider.Optimize(expression, transactionContext.SqlDatabaseContext.SqlDataTypeProvider.GetTypeForEnums());

                acquisition.SqlDatabaseCommandsContext.Delete((SqlDeleteExpression)expression);
            }
        }
        internal Expression ApplyPolicy(Expression expression, MemberInfo member)
        {
            List <LambdaExpression> ops;

            if (Operations.TryGetValue(member, out ops))
            {
                var result = expression;
                foreach (var fnOp in ops)
                {
                    var pop = PartialEvaluator.Eval(fnOp, ExpressionHelper.CanBeEvaluatedLocally);
                    result = QueryBinder.Bind(ExpressionBuilder, this, Expression.Invoke(pop, result));
                }
                var projection = (ProjectionExpression)result;
                if (projection.Type != expression.Type)
                {
                    var fnAgg = Aggregator.GetAggregator(expression.Type, projection.Type);
                    projection = new ProjectionExpression(projection.Select, projection.Projector, fnAgg);
                }
                return(projection);
            }
            return(expression);
        }
示例#11
0
        /// <summary>
        /// Apply mapping translations to this expression
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual Expression Translate(Expression expression)
        {
            // convert references to LINQ operators into query specific nodes
            expression = QueryBinder.Bind(this, expression);

            // move aggregate computations so they occur in same select as group-by
            expression = AggregateRewriter.Rewrite(expression);

            // do reduction so duplicate association's are likely to be clumped together
            expression = UnusedColumnRemover.Remove(expression);
            expression = RedundantColumnRemover.Remove(expression);
            expression = RedundantSubqueryRemover.Remove(expression);
            expression = RedundantJoinRemover.Remove(expression);

            // convert references to association properties into correlated queries
            expression = RelationshipBinder.Bind(this, expression);

            // clean up after ourselves! (multiple references to same association property)
            expression = RedundantColumnRemover.Remove(expression);
            expression = RedundantJoinRemover.Remove(expression);

            return(expression);
        }
示例#12
0
        public override void Delete(Type type, IEnumerable <DataAccessObject> dataAccessObjects)
        {
            var typeDescriptor = this.DataAccessModel.GetTypeDescriptor(type);
            var parameter      = Expression.Parameter(typeDescriptor.Type, "value");

            Expression body = null;

            foreach (var dataAccessObject in dataAccessObjects)
            {
                var currentExpression = Expression.Equal(parameter, Expression.Constant(dataAccessObject));

                if (body == null)
                {
                    body = currentExpression;
                }
                else
                {
                    body = Expression.OrElse(body, currentExpression);
                }
            }

            if (body == null)
            {
                return;
            }

            var condition  = Expression.Lambda(body, parameter);
            var expression = (Expression)Expression.Call(null, GetDeleteMethod(typeDescriptor.Type), Expression.Constant(null, typeDescriptor.Type), condition);

            expression = Evaluator.PartialEval(expression);
            expression = QueryBinder.Bind(this.DataAccessModel, expression, null, null);
            expression = SqlObjectOperandComparisonExpander.Expand(expression);
            expression = SqlQueryProvider.Optimize(expression, this.SqlDatabaseContext.SqlDataTypeProvider.GetTypeForEnums());

            this.Delete((SqlDeleteExpression)expression);
        }
示例#13
0
 /// <summary>
 /// Apply mapping to a sub query expression
 /// </summary>
 /// <param name="expression"></param>
 /// <returns></returns>
 public virtual Expression ApplyMapping(Expression expression)
 {
     return(QueryBinder.Bind(this, expression));
 }
示例#14
0
        internal static Expression GetMemberExpression(TranslateContext transContext, Expression root, IProperty property)
        {
            if (property is RelationProperty relationProprety)
            {
                //所关联的实体类型
                var relMetadata = EntityMetadataUnity.GetEntityMetadata(relationProprety.RelationalType);
                var projection  = GetTableQuery(transContext, relMetadata, false, false);

                Expression parentExp = null, childExp = null;
                var        ship = RelationshipUnity.GetRelationship(relationProprety);

                if (ship.ThisType != relationProprety.EntityType)
                {
                    parentExp = projection.Projector;
                    childExp  = root;
                }
                else
                {
                    parentExp = root;
                    childExp  = projection.Projector;
                }

                var where = ship.Keys.Select(r =>
                                             GetMemberExpression(transContext, parentExp, r.ThisProperty).Equal(GetMemberExpression(transContext, childExp, r.OtherProperty)))
                            .Aggregate(Expression.And);

                var newAlias = new TableAlias();
                var pc       = ColumnProjector.ProjectColumns(CanBeColumnExpression, projection.Projector, null, newAlias, projection.Select.Alias);

                var aggregator = GetAggregator(property.Type, typeof(IEnumerable <>).MakeGenericType(pc.Projector.Type));
                var result     = new ProjectionExpression(
                    new SelectExpression(newAlias, pc.Columns, projection.Select, where),
                    pc.Projector, aggregator, projection.IsAsync, projection.IsNoTracking
                    );

                return(transContext.QueryPolicy.ApplyPolicy(result, property.Info.ReflectionInfo, ex => QueryBinder.Bind(transContext, ex)));
            }

            if (root is TableExpression table)
            {
                if (property is SubqueryProperty sqProperty)
                {
                    return(new SubqueryColumnExpression(property.Type, table.Alias, property.Info.FieldName, sqProperty.Subquery));
                }
                else if (property is ISavedProperty)
                {
                    return(new ColumnExpression(property.Type, table.Alias, property.Name, property.Info));
                }
            }

            return(QueryBinder.BindMember(root, property.Info.ReflectionInfo));
        }
示例#15
0
        internal static ProjectionExpression GetTableQuery(TranslateContext transContext, EntityMetadata entity, bool isNoTracking, bool isAsync)
        {
            var tableAlias  = new TableAlias();
            var selectAlias = new TableAlias();
            var entityType  = entity.EntityType;
            var table       = new TableExpression(tableAlias, entity.TableName, entityType);

            var projector = GetTypeProjection(transContext, table, entity);
            var pc        = ColumnProjector.ProjectColumns(CanBeColumnExpression, projector, null, selectAlias, tableAlias);

            var proj = new ProjectionExpression(
                new SelectExpression(selectAlias, pc.Columns, table, null),
                pc.Projector, isAsync, isNoTracking
                );

            return((ProjectionExpression)transContext.QueryPolicy.ApplyPolicy(proj, entityType, ex => QueryBinder.Bind(transContext, ex)));
        }
示例#16
0
        internal Expression GetExecutionPlan(Expression expression)
        {
            LambdaExpression lambda = expression as LambdaExpression;

            if (lambda != null)
            {
                expression = lambda.Body;
            }

            var translation = expression;

            translation = PartialEvaluator.Eval(expression, ExpressionHelper.CanBeEvaluatedLocally);
            translation = FunctionBinder.Bind(this, translation);
            //translation = PartialEvaluator.Eval(translation, ExpressionHelper.CanBeEvaluatedLocally);
            translation = QueryBinder.Bind(ExpressionBuilder, this, translation);


            translation = AggregateRewriter.Rewrite(Dialect, translation);
            translation = UnusedColumnRemover.Remove(translation);
            translation = RedundantColumnRemover.Remove(translation);
            translation = RedundantSubqueryRemover.Remove(translation);
            translation = RedundantJoinRemover.Remove(translation);

            var bound = RelationshipBinder.Bind(ExpressionBuilder, translation);

            if (bound != translation)
            {
                translation = bound;
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }
            translation = ComparisonRewriter.Rewrite(ExpressionBuilder, translation);

            var rewritten = RelationshipIncluder.Include(ExpressionBuilder, this, translation);

            if (rewritten != translation)
            {
                translation = rewritten;
                translation = UnusedColumnRemover.Remove(translation);
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantSubqueryRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }

            rewritten = SingletonProjectionRewriter.Rewrite(this.ExpressionBuilder, translation);
            if (rewritten != translation)
            {
                translation = rewritten;
                translation = UnusedColumnRemover.Remove(translation);
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantSubqueryRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }

            rewritten = ClientJoinedProjectionRewriter.Rewrite(this, translation);
            if (rewritten != translation)
            {
                translation = rewritten;
                translation = UnusedColumnRemover.Remove(translation);
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantSubqueryRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }

            //
            translation = this.ExpressionBuilder.Translate(translation);

            var        parameters = lambda != null ? lambda.Parameters : null;
            Expression provider   = Find(expression, parameters, typeof(InternalDbContext));

            if (provider == null)
            {
                Expression rootQueryable = Find(expression, parameters, typeof(IQueryable));
                provider = Expression.Property(rootQueryable, typeof(IQueryable).GetProperty("Provider"));
            }

            return(ExecutionBuilder.Build(this.Dialect, this, translation, provider));
        }
示例#17
0
        private PrivateExecuteResult <T> PrivateExecute <T>(Expression expression)
        {
            var projectionExpression = expression as SqlProjectionExpression;

            if (projectionExpression == null)
            {
                expression = Evaluator.PartialEval(expression);

                if (this.RelatedDataAccessObjectContext == null)
                {
                    expression = QueryBinder.Bind(this.DataAccessModel, expression, null, null);
                }
                else
                {
                    expression = QueryBinder.Bind(this.DataAccessModel, expression, this.RelatedDataAccessObjectContext.ElementType, this.RelatedDataAccessObjectContext.ExtraCondition);
                }

                projectionExpression = (SqlProjectionExpression)Optimize(expression, this.SqlDatabaseContext.SqlDataTypeProvider.GetTypeForEnums(), true);
            }

            ProjectorCacheInfo cacheInfo;

            var columns = projectionExpression.Select.Columns.Select(c => c.Name);

            var formatResult = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(projectionExpression, SqlQueryFormatterOptions.Default);

            var placeholderValues = PlaceholderValuesCollector.CollectValues(expression);

            var key = new ProjectorCacheKey(projectionExpression, this.SqlDatabaseContext);

            var projectorCache = this.SqlDatabaseContext.projectorCache;

            if (!projectorCache.TryGetValue(key, out cacheInfo))
            {
                var projectionLambda = ProjectionBuilder.Build(this.DataAccessModel, this.SqlDatabaseContext, projectionExpression.Projector, columns);

                cacheInfo.elementType = projectionLambda.Body.Type;
                cacheInfo.projector   = projectionLambda.Compile();

                var aggregates = AggregateFinder.Find(projectionExpression);

                if (aggregates.Count == 1)
                {
                    cacheInfo.sqlAggregateType = aggregates.First().AggregateType;
                }

                var newCache = new Dictionary <ProjectorCacheKey, ProjectorCacheInfo>(projectorCache, ProjectorCacheEqualityComparer.Default);

                if (!projectorCache.ContainsKey(key))
                {
                    newCache[key] = cacheInfo;
                }

                this.SqlDatabaseContext.projectorCache = newCache;
            }

            var elementType         = TypeHelper.GetElementType(cacheInfo.elementType);
            var concreteElementType = elementType;

            if (elementType.IsDataAccessObjectType())
            {
                Type type;
                TypeHelper.GetElementType(cacheInfo.elementType);
                elementType         = this.DataAccessModel.GetDefinitionTypeFromConcreteType(elementType);
                concreteElementType = this.DataAccessModel.GetConcreteTypeFromDefinitionType(elementType);

                if (this.RelatedDataAccessObjectContext == null)
                {
                    type = typeof(DataAccessObjectProjector <,>);
                }
                else
                {
                    type = typeof(RelatedDataAccessObjectProjector <,>);
                }

                return(new PrivateExecuteResult <T>
                       (
                           (IEnumerable <T>)Activator.CreateInstance
                           (
                               type.MakeGenericType(elementType, concreteElementType),
                               this,
                               this.DataAccessModel,
                               formatResult,
                               this.SqlDatabaseContext,
                               cacheInfo.projector,
                               this.RelatedDataAccessObjectContext,
                               projectionExpression.SelectFirstType,
                               cacheInfo.sqlAggregateType,
                               projectionExpression.IsDefaultIfEmpty,
                               placeholderValues
                           ),
                           projectionExpression.SelectFirstType,
                           cacheInfo.sqlAggregateType,
                           projectionExpression.IsDefaultIfEmpty,
                           projectionExpression.DefaultValueExpression
                       ));
            }
            else
            {
                return(new PrivateExecuteResult <T>
                       (
                           (IEnumerable <T>)Activator.CreateInstance
                           (
                               typeof(ObjectProjector <,>).MakeGenericType(elementType, concreteElementType),
                               this,
                               this.DataAccessModel,
                               formatResult,
                               this.SqlDatabaseContext,
                               cacheInfo.projector,
                               this.RelatedDataAccessObjectContext,
                               projectionExpression.SelectFirstType,
                               cacheInfo.sqlAggregateType,
                               projectionExpression.IsDefaultIfEmpty,
                               placeholderValues
                           ),
                           projectionExpression.SelectFirstType,
                           cacheInfo.sqlAggregateType,
                           projectionExpression.IsDefaultIfEmpty,
                           projectionExpression.DefaultValueExpression
                       ));
            }
        }
        private Expression TranslateInternal(TranslateContext transContext, Expression expression)
        {
            var translation = QueryBinder.Bind(transContext, expression);

            translation = LogicalDeleteFlagRewriter.Rewrite(translation);
            translation = GlobalQueryPolicyRewriter.Rewrite(translation);
            translation = AggregateRewriter.Rewrite(translation);
            translation = UnusedColumnRemover.Remove(translation);
            translation = RedundantColumnRemover.Remove(translation);
            translation = RedundantSubqueryRemover.Remove(translation);
            translation = RedundantJoinRemover.Remove(translation);

            var bound = RelationshipBinder.Bind(transContext, translation);

            if (bound != translation)
            {
                translation = bound;
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }

            translation = ComparisonRewriter.Rewrite(translation);

            Expression rewritten;

            if (transContext.QueryPolicy != null)
            {
                rewritten = RelationshipIncluder.Include(transContext, translation);
                if (rewritten != translation)
                {
                    translation = rewritten;
                    translation = UnusedColumnRemover.Remove(translation);
                    translation = RedundantColumnRemover.Remove(translation);
                    translation = RedundantSubqueryRemover.Remove(translation);
                    translation = RedundantJoinRemover.Remove(translation);
                }
            }

            rewritten = SingletonProjectionRewriter.Rewrite(translation);
            if (rewritten != translation)
            {
                translation = rewritten;
                translation = UnusedColumnRemover.Remove(translation);
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantSubqueryRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }

            rewritten = ClientJoinedProjectionRewriter.Rewrite(translation);
            if (rewritten != translation)
            {
                translation = rewritten;
                translation = UnusedColumnRemover.Remove(translation);
                translation = RedundantColumnRemover.Remove(translation);
                translation = RedundantSubqueryRemover.Remove(translation);
                translation = RedundantJoinRemover.Remove(translation);
            }

            translation = BuildExpression(translation);

            return(translation);
        }