/// <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); } }
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); }
/// <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))); } }
/// <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); }
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)))); }
// 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); }
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); }
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)))); }
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)); }
/// <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); }
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); } }
/// <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)); }
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)))); }
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); }