Пример #1
0
        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);
        }
Пример #2
0
 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);
         }
     }
 }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
            }
        }