private void AddComputedStaticExpression(AddValueContext addContext) { SqlTableColumn column = SqlDml.TableColumn(addContext.Statement.Table, addContext.Field.Column.Name); var all = Expression.Call(Expression.Constant(parent.Session.Query), "All", new[] { typeof(T) }); MethodCallExpression selectExpression = Expression.Call( typeof(Queryable), "OrderBy", addContext.Lambda.Type.GetGenericArguments(), all, addContext.Lambda); QueryTranslationResult request = parent.GetRequest(parent.QueryProvider.CreateQuery <T>(selectExpression)); var sqlSelect = ((SqlSelect)request.Query); SqlExpression ex = sqlSelect.OrderBy[0].Expression; var placeholder = ex as SqlPlaceholder; if (placeholder == null) { parent.Bindings.AddRange(request.ParameterBindings); addContext.Statement.AddValue(column, ex); return; } //hack for this case addContext.Lambda = (LambdaExpression)addContext.Lambda.Visit((Expression e) => { if (e.Type != typeof(Session)) { return(e); } return(Expression.Property(addContext.Lambda.Parameters[0], "Session")); }); AddComputedExpression(addContext); }
public void AddValues() { foreach (SetDescriptor descriptor in Descriptors) { var addContext = new AddValueContext { Descriptor = descriptor, Lambda = Expression.Lambda( typeof(Func <,>).MakeGenericType(typeof(T), descriptor.Expression.Type), descriptor.Expression, descriptor.Parameter), Statement = Statement }; descriptor.Expression.Visit( delegate(ParameterExpression p) { // ReSharper disable AccessToModifiedClosure if (p == descriptor.Parameter) { // ReSharper restore AccessToModifiedClosure addContext.EntityParamExists = true; } return(p); }); addContext.SubqueryExists = descriptor.Expression.IsContainsQuery(); addContext.Field = descriptor.Field; if (addContext.Field.IsEntitySet) { throw new NotSupportedException("EntitySets are not supported"); } if (addContext.Field.IsEntity) { AddEntityValue(addContext); continue; } if (!addContext.EntityParamExists && addContext.SubqueryExists) { AddComputedStaticExpression(addContext); } else if (addContext.EntityParamExists || addContext.SubqueryExists) { AddComputedExpression(addContext); } else { AddConstantValue(addContext); } } }
private void AddConstantValue(AddValueContext addContext) { SqlTableColumn column = SqlDml.TableColumn(addContext.Statement.Table, addContext.Field.Column.Name); SqlExpression value; object constant = Expression.Lambda(addContext.Lambda.Body, null).Compile().DynamicInvoke(); if (constant == null) { value = SqlDml.Null; } else { QueryParameterBinding binding = parent.QueryBuilder.CreateParameterBinding(constant.GetType(), () => constant); parent.Bindings.Add(binding); value = binding.ParameterReference; } addContext.Statement.AddValue(column, value); }
private void AddComputedExpression(AddValueContext addContext) { SqlTableColumn column = SqlDml.TableColumn(addContext.Statement.Table, addContext.Field.Column.Name); var all = Expression.Call(Expression.Constant(parent.Session.Query), "All", new[] { typeof(T) }); MethodCallExpression selectExpression = Expression.Call( typeof(Queryable), "OrderBy", addContext.Lambda.Type.GetGenericArguments(), all, addContext.Lambda); QueryTranslationResult request = parent.GetRequest(parent.QueryProvider.CreateQuery <T>(selectExpression)); var sqlSelect = ((SqlSelect)request.Query); SqlExpression ex = sqlSelect.OrderBy[0].Expression; parent.Bindings.AddRange(request.ParameterBindings); if (parent.JoinedTableRef != null) { ex.AcceptVisitor(new ComputedExpressionSqlVisitor(sqlSelect.From, parent.JoinedTableRef)); } addContext.Statement.AddValue(column, ex); }
private void AddEntityValue(AddValueContext addContext) { if (addContext.EntityParamExists) { throw new NotSupportedException("Expressions with reference to updating entity are not supported"); } var methodCall = addContext.Descriptor.Expression as MethodCallExpression; int i; if (methodCall != null) { if (methodCall.Method.DeclaringType == typeof(QueryEndpoint) && methodCall.Method.Name.In("Single", "SingleOrDefault")) { object[] keys; if (methodCall.Arguments[0].Type == typeof(Key) || methodCall.Arguments[0].Type.IsSubclassOf(typeof(Key))) { var key = (Key)methodCall.Arguments[0].Invoke(); keys = new object[key.Value.Count]; for (i = 0; i < keys.Length; i++) { keys[i] = key.Value.GetValue(i); } } else { keys = (object[])methodCall.Arguments[0].Invoke(); } i = -1; foreach (ColumnInfo column in addContext.Field.Columns) { i++; SqlExpression value; if (keys[i] == null) { value = SqlDml.Null; } else { object v = keys[i]; QueryParameterBinding binding = parent.QueryBuilder.CreateParameterBinding(v.GetType(), () => v); parent.Bindings.Add(binding); value = binding.ParameterReference; } SqlTableColumn c = SqlDml.TableColumn(addContext.Statement.Table, column.Name); addContext.Statement.AddValue(c, value); } return; } if (methodCall.Method.DeclaringType == typeof(Queryable) && methodCall.Method.Name.In("Single", "SingleOrDefault", "First", "FirstOrDefault")) { Expression exp = methodCall.Arguments[0]; TypeInfo info = parent.GetTypeInfo(addContext.Field.ValueType); if (methodCall.Arguments.Count == 2) { exp = Expression.Call( typeof(Queryable), "Where", new[] { info.UnderlyingType }, exp, methodCall.Arguments[1]); } exp = Expression.Call(typeof(Queryable), "Take", new[] { info.UnderlyingType }, exp, Expression.Constant(1)); i = -1; foreach (FieldInfo field in info.Key.Fields) { i++; ParameterExpression p = Expression.Parameter(info.UnderlyingType); LambdaExpression lambda = Expression.Lambda( typeof(Func <,>).MakeGenericType(info.UnderlyingType, field.ValueType), Expression.MakeMemberAccess(p, field.UnderlyingProperty), p); IQueryable q = ((IQueryProvider)parent.QueryProvider).CreateQuery( Expression.Call(typeof(Queryable), "Select", new[] { info.UnderlyingType, field.ValueType }, exp, lambda)); QueryTranslationResult request = parent.GetRequest(field.ValueType, q); parent.Bindings.AddRange(request.ParameterBindings); SqlTableColumn c = SqlDml.TableColumn(addContext.Statement.Table, addContext.Field.Columns[i].Name); addContext.Statement.AddValue(c, SqlDml.SubQuery((ISqlQueryExpression)request.Query)); } return; } } i = -1; var entity = (IEntity)Expression.Lambda(addContext.Lambda.Body, null).Compile().DynamicInvoke(); foreach (ColumnInfo column in addContext.Field.Columns) { i++; SqlExpression value; if (entity == null) { value = SqlDml.Null; } else { object v = entity.Key.Value.GetValue(i); QueryParameterBinding binding = parent.QueryBuilder.CreateParameterBinding(v.GetType(), () => v); parent.Bindings.Add(binding); value = binding.ParameterReference; } SqlTableColumn c = SqlDml.TableColumn(addContext.Statement.Table, column.Name); addContext.Statement.AddValue(c, value); } }