protected override 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, v.QueryType)), false); Expression[] values = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray(); if (command is OInsertCommandExpression) { // insert will directly return a populated instance without the need for a BlockCommandExpression // to execute first an INSERT followed by a SELECT - so here we utilize the same Execute method // as a projection in order to map the returned values into an entity instance in a single call return ExecuteInsert((OInsertCommandExpression)command, qc, values); } else if (command is OUpdateCommandExpression) { // update will directly return a populated instance without the need for a BlockCommandExpression // to execute first an INSERT followed by a SELECT - so here we utilize the same Execute method // as a projection in order to map the returned values into an entity instance in a single call return ExecuteUpdate((OUpdateCommandExpression)command, qc, values); } else { ProjectionExpression projection = ProjectionFinder.FindProjection(expression); if (projection != null) { return this.ExecuteProjection(projection, qc, values); } } Expression plan = Expression.Call(this.Executor, "ExecuteCommand", null, Expression.Constant(qc), Expression.NewArrayInit(typeof(object), values) ); return plan; }
private Expression ExecuteUpdate(OUpdateCommandExpression update, QueryCommand command, Expression[] values) { var reader = Expression.Parameter(typeof(FieldReader), "r" + nReaders++); var saveScope = this.scope; var projection = this.Linguist.Translator.Mapper.GetQueryExpression(new OMappingEntity(update.Projection.Projector.Type, _repoType)); var fields = new OFieldFinder().Find(update.Projection.Projector).Select(fe => new FieldDeclaration(fe.Name, fe, fe.QueryType)).ToArray(); var alias = ((FieldExpression)fields[0].Expression).Alias; this.scope = new BuilderScope( this.scope, reader, alias, fields) { UseOrdinalMapping = false // we can't guarantee the order that properties will be returned, so we need to read by name }; //var projector = Expression.Lambda(this.Visit(update.Projection.Projector), reader); var projector = RedirectProjector(update.Projection.Projector, reader, false); this.scope = saveScope; var entity = EntityFinder.Find(update.Projection.Projector); // call low-level execute directly on supplied DbQueryProvider Expression result = Expression.Call(this.Executor, "Execute", new Type[] { update.Identifiable.Entity.EntityType }, Expression.Constant(command), projector, Expression.Constant(entity, typeof(MappingEntity)), Expression.NewArrayInit(typeof(object), values) ); if (update.Projection.Aggregator != null) { // apply aggregator result = DbExpressionReplacer.Replace(update.Projection.Aggregator.Body, update.Projection.Aggregator.Parameters[0], result); } return result; }
protected override Expression ExecuteProjection(ProjectionExpression projection, QueryCommand command, Expression[] values) { var saveScope = this.Scope; ParameterExpression reader = Expression.Parameter(typeof(FieldReader), "r" + nReaders++); this.Scope = new BuilderScope(this.Scope, reader, projection.Select.Alias, projection.Select.Fields) { UseOrdinalMapping = false // orient cannot guarantee ordinally mapped results - must map by name }; var projector = RedirectProjector(projection.Projector, reader, true); this.Scope = saveScope; var entity = EntityFinder.Find(projection.Projector); if (entity != null && entity.EntityType == typeof(_Thing)) { entity = new OMappingEntity(typeof(IIdentifiable),_repoType); } string methExecute = "Execute"; // call low-level execute directly on supplied DbQueryProvider Expression result = Expression.Call(this.Executor, methExecute, new Type[] { projector.Body.Type }, Expression.Constant(command), projector, Expression.Constant(entity, typeof(MappingEntity)), Expression.NewArrayInit(typeof(object), values) ); if (projection.Aggregator != null) { if (projector.ReturnType != projection.Aggregator.Parameters[0].Type.GetGenericArguments()[0]) { // we probably swaped out an Identifiable type for IIdentifiable, so we need to rebuild the projection // using the interface, otherwise we'll get cast failures downstream projection = new ProjectionExpression( projection.Select, projector, Aggregator.GetAggregator(projector.ReturnType, projection.Aggregator.Parameters[0].Type.GetGenericTypeDefinition().MakeGenericType(projector.ReturnType))); } // apply aggregator result = DbExpressionReplacer.Replace(projection.Aggregator.Body, projection.Aggregator.Parameters[0], result); } return result; }