Ejemplo n.º 1
0
        /// <summary>
        /// 收集嵌套的参数并生成 <see cref="ParameterCollection"/> 的表达式。
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private Expression CreateParameterCollectionExpression(Expression expression)
        {
            var namedValues = NamedValueGatherer.Gather(expression);

            var values = (from v in namedValues
                          let nex = Visit(v.Value)
                                    select nex.NodeType == ExpressionType.Convert ? nex : Expression.Convert(nex, typeof(object))).ToArray();

            if (values.Length > 0)
            {
                var arguments = new List <Expression>();
                var consPar   = ReflectionCache.GetMember("ParameterConstructor", typeof(Parameter), k => k.GetConstructor(new[] { typeof(string), typeof(object) }));

                for (var i = 0; i < namedValues.Count; i++)
                {
                    Expression pv = values[i] is Expression ?
                                    (Expression)values[i] :
                                    Expression.Constant(values[i], typeof(object));

                    var pExp = Expression.New(consPar, Expression.Constant(namedValues[i].Name), pv);
                    arguments.Add(pExp);
                }

                var initExp   = Expression.ListInit(Expression.New(typeof(List <Parameter>)), arguments);
                var consParas = ReflectionCache.GetMember("ParameterCollectionConstructor1", typeof(ParameterCollection), k => k.GetConstructor(new[] { typeof(IEnumerable <Parameter>) }));
                return(Expression.New(consParas, initExp));
            }
            else
            {
                return(MethodCache.ExpNullParameter);
            }
        }
Ejemplo n.º 2
0
        protected virtual void FormatWithParameters(Expression expression)
        {
            var names = NamedValueGatherer.Gather(expression);

            if (names.Count > 0)
            {
                Write("PARAMETERS ");

                for (int i = 0, n = names.Count; i < n; i++)
                {
                    if (i > 0)
                    {
                        Write(", ");
                    }

                    WriteParameterName(names[i].Name);
                    Write(" ");
                    Write(Language.TypeSystem.Format(names[i].QueryType, true));
                }

                Write(";");
                WriteLine(Indentation.Same);
            }
            Visit(expression);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 收集嵌套的参数并生成 <see cref="ParameterCollection"/> 的表达式。
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private Expression CreateParameterCollectionExpression(Expression expression)
        {
            var namedValues = NamedValueGatherer.Gather(expression);
            var values      = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray();

            if (values.Length > 0)
            {
                var arguments   = new List <Expression>();
                var constructor = typeof(Parameter).GetConstructor(new[] { typeof(string), typeof(object) });

                for (var i = 0; i < namedValues.Count; i++)
                {
                    Expression pv = values[i] is Expression ?
                                    (Expression)values[i] :
                                    Expression.Constant(values[i], typeof(object));

                    var pExp = Expression.New(constructor, Expression.Constant(namedValues[i].Name), pv);
                    arguments.Add(pExp);
                }

                var listExp = Expression.ListInit(Expression.New(typeof(List <Parameter>)), arguments);
                return(Expression.New(typeof(ParameterCollection).GetConstructors()[1], listExp));
            }
            else
            {
                return(Expression.Constant(null, typeof(ParameterCollection)));
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Builds the execute command.
        /// </summary>
        /// <param name="command">The command.</param>
        /// <returns></returns>
        protected virtual Expression BuildExecuteCommand(CommandExpression command)
        {
            // parameterize query
            var expression = this.Parameterize(command);

            string commandText = this.linguist.Format(expression);
            ReadOnlyCollection <NamedValueExpression> namedValues = NamedValueGatherer.Gather(expression);
            QueryCommand qc = new QueryCommand(commandText, namedValues.Select(v => new QueryParameter(v.Name, v.Type)));

            Expression[] values = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray();

            ProjectionExpression projection = ProjectionFinder.FindProjection(expression);

            if (projection != null)
            {
                return(this.ExecuteProjection(projection, false, qc, values));
            }

            Expression plan = Expression.Call(this.executor, "ExecuteCommand", null,
                                              Expression.Constant(qc),
                                              Expression.NewArrayInit(typeof(object), values)
                                              );

            return(plan);
        }
Ejemplo n.º 5
0
        private Expression BuildExecuteBatch(BatchCommandExpression batch)
        {
            var operation = Parameterize(batch.Operation.Body);

            var result      = translator(operation);
            var namedValues = NamedValueGatherer.Gather(operation);

            var table = new DataTable();

            foreach (var nv in namedValues)
            {
                var info = GetPropertyInfoFromExpression(nv.Value);
                table.Columns.Add(nv.Name, info.DataType.Value.FromDbType());
            }

            var parameters = namedValues.ToDictionary(s => s.Name, s =>
            {
                var expression = s.Value;
                if (ConvertManager.GetConverter(expression.Type) != null)
                {
                    var info    = GetPropertyInfoFromExpression(expression);
                    var convExp = Expression.Call(null, MthGetConverter, Expression.Constant(expression.Type));
                    expression  = Expression.Call(convExp, MthConvertTo, expression, Expression.Constant((DbType)info.DataType));
                }

                var lambda = Expression.Lambda(expression, batch.Operation.Parameters[1]).Compile();
                return(lambda);
            });

            var entities = (IEnumerable)((ConstantExpression)batch.Input).Value;

            foreach (IEntity entity in entities)
            {
                var row = table.NewRow();
                foreach (var nv in parameters)
                {
                    row[nv.Key] = nv.Value.DynamicInvoke(entity) ?? DBNull.Value;
                }

                table.Rows.Add(row);
            }

            Expression plan = Expression.Call(executor, MthUpdate,
                                              Expression.Constant(table),
                                              Expression.Constant((SqlCommand)result.QueryText),
                                              Expression.Constant(null, typeof(SqlCommand)),
                                              Expression.Constant(null, typeof(SqlCommand))
                                              );

            if (operation.NodeType != (ExpressionType)DbExpressionType.Insert)
            {
                return(plan);
            }

            return(Expression.Call(typeof(ExecutionBuilder), nameof(ExecutionBuilder.UpdateEntities), null,
                                   plan,
                                   Expression.Constant(table, typeof(DataTable)),
                                   Expression.Constant(entities, typeof(IEnumerable))));
        }
Ejemplo n.º 6
0
        // end mike

        private Expression ExecuteProjection(ProjectionExpression projection, bool okayToDefer)
        {
            okayToDefer &= (receivingMember != null && policy.IsDeferLoaded(receivingMember));

            // parameterize query
            projection = (ProjectionExpression)policy.Mapping.Language.Parameterize(projection);

            if (scope != null)
            {
                // also convert references to outer alias to named values!  these become SQL parameters too
                projection = (ProjectionExpression)OuterParameterizer.Parameterize(scope.Alias, projection);
            }

            var saveScope = scope;
            ParameterExpression reader = Expression.Parameter(typeof(DbDataReader), "r" + nReaders++);

            scope = new Scope(scope, reader, projection.Source.Alias, projection.Source.Columns);
            LambdaExpression projector = Expression.Lambda(Visit(projection.Projector), reader);

            scope = saveScope;
            List <string> columnNames = ColumnNamedGatherer.Gather(projector.Body);           //mike
            string        commandText = policy.Mapping.Language.Format(projection.Source);
            var           namedValues = NamedValueGatherer.Gather(projection.Source);
            var           names       = namedValues.Select(v => v.Name).ToArray();

            Expression[] values = namedValues.Select(v => Expression.Convert(
                                                         v.ParameterBindingAction != null ? v.ParameterBindingAction((ConstantExpression)v.Value) : Visit(v.Value),
                                                         typeof(object))).ToArray();

            string methExecute = okayToDefer
                                     ? "ExecuteDeferred"
                                     : "Execute";

            if (okayToDefer)
            {
            }

            // call low-level execute directly on supplied DbQueryProvider
            Expression result = Expression.Call(provider, methExecute, new[] { projector.Body.Type },
                                                Expression.New(
                                                    typeof(QueryCommand <>).MakeGenericType(projector.Body.Type).
                                                    GetConstructors()[0],
                                                    Expression.Constant(commandText),
                                                    Expression.Constant(names),
                                                    projector, Expression.Constant(columnNames)
                                                    ),
                                                Expression.NewArrayInit(typeof(object), values)
                                                );

            if (projection.Aggregator != null)
            {
                // apply aggregator
                result = DbExpressionReplacer.Replace(projection.Aggregator.Body, projection.Aggregator.Parameters[0],
                                                      result);
            }
            return(result);
        }
Ejemplo n.º 7
0
        protected virtual Expression BuildExecuteCommand(CommandExpression command)
        {
            // parameterize query
            var expression = this.Parameterize(command);

            var cdu = (command as CDUCommandExpression);

            string commandText = this.dbContext.BuildSql(expression);
            ReadOnlyCollection <NamedValueExpression> namedValues = NamedValueGatherer.Gather(expression);

            Expression[] values     = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray();
            var          parameters = namedValues.Select(v => new NamedParameter(v.Name, v.Type, v.SqlType)).ToArray();

            ProjectionExpression projection = ProjectionFinder.FindProjection(expression);

            if (projection != null)
            {
                return(this.ExecuteProjection(projection, false, commandText, parameters, values));
            }

            bool supportVersionCheck = false;
            var  delete = cdu as DeleteCommand;

            if (delete != null)
            {
                supportVersionCheck = delete.SupportsVersionCheck;
            }
            var update = cdu as UpdateCommand;

            if (update != null)
            {
                supportVersionCheck = update.SupportsVersionCheck;
            }

            var commandContext = Expression.New(
                MethodRepository.CommandContext.New,
                Expression.Constant(commandText),
                Expression.Constant(parameters),
                Expression.NewArrayInit(typeof(object), values),
                Expression.Constant(cdu.Table.Mapping.EntityType, Types.Type),
                Expression.Constant((OperationType)cdu.DbNodeType),
                Expression.Constant(supportVersionCheck),
                Expression.Constant(cdu.Instance))
            ;

            //Expression plan = Expression.Call(this.executor, "ExecuteNonQuery", new Type[] { (command as CDUCommandExpression).Table.Entity.EntityType },
            //    Expression.Constant(commandText),
            //     Expression.Constant(parameters),
            //    Expression.NewArrayInit(typeof(object), values)
            //    );

            Expression plan = Expression.Call(this.executor, "ExecuteNonQuery", null, commandContext);

            return(plan);
        }
Ejemplo n.º 8
0
        private Expression BuildExecuteBatch(BatchCommandExpression batch)
        {
            var operation = Parameterize(batch.Operation.Body);

            var result      = translator(operation);
            var namedValues = NamedValueGatherer.Gather(operation);

            var table = new DataTable();

            foreach (var nv in namedValues)
            {
                var t = nv.Type.GetNonNullableType();
                if (t.IsEnum)
                {
                    t = typeof(int);
                }

                table.Columns.Add(nv.Name, t);
            }

            var parameters = namedValues.ToDictionary(s => s.Name, s => Expression.Lambda(s.Value, batch.Operation.Parameters[1]).Compile());

            var entities = (IEnumerable)((ConstantExpression)batch.Input).Value;

            foreach (IEntity entity in entities)
            {
                var row = table.NewRow();
                foreach (var nv in parameters)
                {
                    row[nv.Key] = nv.Value.DynamicInvoke(entity) ?? DBNull.Value;
                }

                table.Rows.Add(row);
            }

            Expression plan = Expression.Call(executor, MthUpdate,
                                              Expression.Constant(table),
                                              Expression.Constant((SqlCommand)result.QueryText),
                                              Expression.Constant(null, typeof(SqlCommand)),
                                              Expression.Constant(null, typeof(SqlCommand))
                                              );

            if (operation.NodeType != (ExpressionType)DbExpressionType.Insert)
            {
                return(plan);
            }

            return(Expression.Call(typeof(ExecutionBuilder), nameof(ExecutionBuilder.UpdateEntities), null,
                                   plan,
                                   Expression.Constant(table, typeof(DataTable)),
                                   Expression.Constant(entities, typeof(IEnumerable))));
        }
Ejemplo n.º 9
0
        private Expression ExecuteProjection(ProjectionExpression projection, bool okayToDefer)
        {
            projection = (ProjectionExpression)this.Parameterize(projection);

            if (this.scope != null)
            {
                // also convert references to outer alias to named values!  these become SQL parameters too
                projection = (ProjectionExpression)OuterParameterizer.Parameterize(this.scope.Alias, projection);
            }

            string commandText = this.dbContext.BuildSql(projection.Select);

            ReadOnlyCollection <NamedValueExpression> namedValues = NamedValueGatherer.Gather(projection.Select);

            Expression[] values = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray();

            return(this.ExecuteProjection(projection, okayToDefer, commandText, namedValues.Select(v => new NamedParameter(v.Name, v.Type, v.SqlType)).ToArray(), values));
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Builds the execute batch.
        /// </summary>
        /// <param name="batch">The batch.</param>
        /// <returns></returns>
        protected virtual Expression BuildExecuteBatch(BatchExpression batch)
        {
            // parameterize query
            Expression operation = this.Parameterize(batch.Operation.Body);

            string       commandText = this.linguist.Format(operation);
            var          namedValues = NamedValueGatherer.Gather(operation);
            QueryCommand command     = new QueryCommand(commandText, namedValues.Select(v => new QueryParameter(v.Name, v.Type)));

            Expression[] values = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray();

            Expression paramSets = Expression.Call(typeof(Enumerable), "Select", new Type[] { batch.Operation.Parameters[1].Type, typeof(object[]) }, batch.Input, Expression.Lambda(Expression.NewArrayInit(typeof(object), values), new[] { batch.Operation.Parameters[1] }));

            Expression plan = null;

            ProjectionExpression projection = ProjectionFinder.FindProjection(operation);

            if (projection != null)
            {
                var saveScope = this.scope;
                ParameterExpression reader = Expression.Parameter(typeof(FieldReader), "r" + nReaders++);
                this.scope = new Scope(this.scope, reader, projection.Select.Alias, projection.Select.Columns);
                LambdaExpression projector = Expression.Lambda(this.Visit(projection.Projector), reader);
                this.scope = saveScope;

                var entity = EntityFinder.Find(projection.Projector);
                command = new QueryCommand(command.CommandText, command.Parameters);

                plan = Expression.Call(this.executor, "ExecuteBatch", new Type[] { projector.Body.Type },
                                       Expression.Constant(command),
                                       paramSets,
                                       projector,
                                       Expression.Constant(entity, typeof(MappingEntity)),
                                       batch.BatchSize,
                                       batch.Stream
                                       );
            }
            else
            {
                plan = Expression.Call(this.executor, "ExecuteBatch", null, Expression.Constant(command), paramSets, batch.BatchSize, batch.Stream);
            }

            return(plan);
        }
Ejemplo n.º 11
0
        protected internal virtual void FormatWithParameters(Expression expression)
        {
            var names = NamedValueGatherer.Gather(expression);

            if (names.Count > 0)
            {
                this.Append("PARAMETERS ");
                for (int i = 0, n = names.Count; i < n; i++)
                {
                    if (i > 0)
                    {
                        this.Append(", ");
                    }
                    this.AppendParameterName(names[i].Name);
                    this.Append(" ");
                    this.Append(GetVariableDeclaration(names[i].SqlType, true, null));
                }
                this.Append(";");
                this.AppendLine(Indentation.Same);
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Executes the projection.
        /// </summary>
        /// <param name="projection">The projection.</param>
        /// <param name="okayToDefer">if set to <c>true</c> [okay to defer].</param>
        /// <returns></returns>
        private Expression ExecuteProjection(ProjectionExpression projection, bool okayToDefer)
        {
            // parameterize query
            projection = (ProjectionExpression)this.Parameterize(projection);

            if (this.scope != null)
            {
                // also convert references to outer alias to named values!  these become SQL parameters too
                projection = (ProjectionExpression)OuterParameterizer.Parameterize(this.scope.Alias, projection);
            }

            FixColumnNames(projection);

            string commandText = this.linguist.Format(projection.Select);
            ReadOnlyCollection <NamedValueExpression> namedValues = NamedValueGatherer.Gather(projection.Select);
            QueryCommand command = new QueryCommand(commandText, namedValues.Select(v => new QueryParameter(v.Name, v.Type)));

            Expression[] values = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray();

            return(this.ExecuteProjection(projection, okayToDefer, command, values));
        }
Ejemplo n.º 13
0
        private Expression BuildExecuteBatch(BatchCommandExpression batch)
        {
            var operation = Parameterize(batch.Operation.Body);

            var result      = _translator.Translate(operation);
            var namedValues = NamedValueGatherer.Gather(operation);

            var table = new DataTable();

            foreach (var nv in namedValues)
            {
                var info = GetPropertyInfoFromExpression(nv.Value);
                if (info != null)
                {
                    table.Columns.Add(nv.Name, info.DataType.Value.FromDbType());
                }
                else
                {
                    table.Columns.Add(nv.Name, DataExpressionRow.CreateType(nv.Value.Type));
                }
            }

            var parameters = namedValues.ToDictionary(s => s.Name, s =>
            {
                var expression = s.Value;
                var info       = GetPropertyInfoFromExpression(expression);
                if (info == null)
                {
                    return(expression);
                }

                if (ConvertManager.GetConverter(expression.Type) != null)
                {
                    var convExp = Expression.Call(null, MethodCache.GetConverter, Expression.Constant(expression.Type));
                    expression  = Expression.Call(convExp, MethodCache.ConvertTo, expression, Expression.Constant((DbType)info.DataType));
                }

                return((object)Expression.Lambda(expression, batch.Operation.Parameters[1]).Compile());
            });

            var entities = (IEnumerable)batch.Input.Value;

            foreach (IEntity entity in entities)
            {
                var row = table.NewRow();
                foreach (var nv in parameters)
                {
                    if (nv.Value is Delegate del)
                    {
                        row[nv.Key] = del.DynamicInvoke(entity) ?? DBNull.Value;
                    }
                    else if (nv.Value is Expression exp)
                    {
                        exp = ParameterRewriter.Rewrite(exp, batch.Operation.Parameters[1], entity);
                        var setter = Expression.Lambda(exp, _executor).Compile();
                        row[nv.Key] = DataExpressionRow.Create(exp.Type, setter);
                    }
                }

                table.Rows.Add(row);
            }

            Expression plan;

            if (_isAsync)
            {
                _cancelToken = Expression.Parameter(typeof(CancellationToken), "token");
                plan         = Expression.Call(_executor, MethodCache.DbUpdateAsync,
                                               Expression.Constant(table),
                                               Expression.Constant((SqlCommand)result.QueryText),
                                               Expression.Constant(null, typeof(SqlCommand)),
                                               Expression.Constant(null, typeof(SqlCommand)),
                                               _cancelToken
                                               );
            }
            else
            {
                plan = Expression.Call(_executor, MethodCache.DbUpdate,
                                       Expression.Constant(table),
                                       Expression.Constant((SqlCommand)result.QueryText),
                                       Expression.Constant(null, typeof(SqlCommand)),
                                       Expression.Constant(null, typeof(SqlCommand))
                                       );
            }

            if (operation.NodeType != (ExpressionType)DbExpressionType.Insert)
            {
                return(plan);
            }

            return(Expression.Call(typeof(ExecutionBuilder),
                                   _isAsync ? nameof(ExecutionBuilder.UpdateEntitiesAsync) : nameof(ExecutionBuilder.UpdateEntities), null,
                                   plan,
                                   Expression.Constant(table, typeof(DataTable)),
                                   Expression.Constant(entities, typeof(IEnumerable))));
        }
Ejemplo n.º 14
0
        protected virtual Expression BuildExecuteBatch(BatchExpression batch)
        {
            Expression operation = this.Parameterize(batch.Operation.Body);

            var  cdu        = batch.Operation.Body as CDUCommandExpression;
            Type entityType = null;

            if (cdu != null)
            {
                entityType = cdu.Table.Mapping.EntityType;
            }

            string commandText = this.dbContext.BuildSql(operation);
            var    namedValues = NamedValueGatherer.Gather(operation);
            var    parameters  = namedValues.Select(v => new NamedParameter(v.Name, v.Type, v.SqlType)).ToArray();

            Expression[] values = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray();

            Expression paramSets = Expression.Call(typeof(Enumerable), "Select", new Type[] { batch.Operation.Parameters[1].Type, typeof(object[]) },
                                                   batch.Input,
                                                   Expression.Lambda(Expression.NewArrayInit(typeof(object), values), new[] { batch.Operation.Parameters[1] })
                                                   );

            Expression plan = null;

            ProjectionExpression projection = ProjectionFinder.FindProjection(operation);

            if (projection != null)
            {
                var saveScope = this.scope;
                ParameterExpression reader = Expression.Parameter(typeof(FieldReader), "r" + nReaders++);
                this.scope = new Scope(this.scope, reader, projection.Select.Alias, projection.Select.Columns);
                LambdaExpression projector = Expression.Lambda(this.Visit(projection.Projector), reader);
                this.scope = saveScope;

                // var entity = EntityFinder.Find(projection.Projector);

                var batchContext = Expression.New(typeof(BatchContext <>).MakeGenericType(projector.Body.Type).GetConstructors().FirstOrDefault(),
                                                  Expression.Constant(commandText),
                                                  Expression.Constant(parameters),
                                                  paramSets,
                                                  projector);
                plan = Expression.Call(this.executor, "Batch", new Type[] { projector.Body.Type }, batchContext);
            }
            else
            {
                var batchContext = Expression.New(typeof(BatchContext).GetConstructors().FirstOrDefault(),
                                                  Expression.Constant(commandText),
                                                  Expression.Constant(parameters),
                                                  paramSets,
                                                  Expression.Constant(entityType));

                //plan = Expression.Call(this.executor, "Batch", null,
                //    Expression.Constant(commandText),
                //    Expression.Constant(parameters),
                //    paramSets
                //    );
                plan = Expression.Call(this.executor, "Batch", null, batchContext);
            }

            return(plan);
        }