Esempio n. 1
0
        private CompileResult CompileExpr([NotNull] Expression expr, List <object> queryArgs)
        {
            if (expr == null)
            {
                throw new NotSupportedException("Expression is NULL");
            }
            if (expr is BinaryExpression)
            {
                var bin = (BinaryExpression)expr;

                var leftr  = CompileExpr(bin.Left, queryArgs);
                var rightr = CompileExpr(bin.Right, queryArgs);

                //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null")
                string text;
                if (leftr.CommandText == "?" && leftr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, rightr);
                }
                else if (rightr.CommandText == "?" && rightr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, leftr);
                }
                else
                {
                    text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")";
                }
                return(new CompileResult
                {
                    CommandText = text
                });
            }
            if (expr.NodeType == ExpressionType.Not)
            {
                var operandExpr = ((UnaryExpression)expr).Operand;
                var opr         = CompileExpr(operandExpr, queryArgs);
                var val         = opr.Value;
                if (val is bool)
                {
                    val = !((bool)val);
                }
                return(new CompileResult
                {
                    CommandText = "NOT(" + opr.CommandText + ")",
                    Value = val
                });
            }
            if (expr.NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)expr;
                var args = new CompileResult[call.Arguments.Count];
                var obj  = call.Object != null?CompileExpr(call.Object, queryArgs) : null;

                for (var i = 0; i < args.Length; i++)
                {
                    args[i] = CompileExpr(call.Arguments[i], queryArgs);
                }

                var sqlCall = "";

                if (call.Method.Name == "Like" && args.Length == 2)
                {
                    sqlCall = "(" + args[0].CommandText + " like " + args[1].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 2)
                {
                    sqlCall = "(" + args[1].CommandText + " in " + args[0].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 1)
                {
                    if (call.Object != null && call.Object.Type == typeof(string))
                    {
                        sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + " || '%'))";
                    }
                    else
                    {
                        sqlCall = "(" + args[0].CommandText + " in " + obj.CommandText + ")";
                    }
                }
                else if (call.Method.Name == "StartsWith" && args.Length == 1)
                {
                    sqlCall = "(" + obj.CommandText + " like (" + args[0].CommandText + " || '%'))";
                }
                else if (call.Method.Name == "EndsWith" && args.Length == 1)
                {
                    sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + "))";
                }
                else if (call.Method.Name == "Equals" && args.Length == 1)
                {
                    sqlCall = "(" + obj.CommandText + " = (" + args[0].CommandText + "))";
                }
                else if (call.Method.Name == "ToLower")
                {
                    sqlCall = "(lower(" + obj.CommandText + "))";
                }
                else if (call.Method.Name == "ToUpper")
                {
                    sqlCall = "(upper(" + obj.CommandText + "))";
                }
                else if (call.Method.Name == "Replace" && args.Length == 2)
                {
                    sqlCall = "(replace(" + obj.CommandText + ", " + args[0].CommandText + ", " + args[1].CommandText + "))";
                }
                else
                {
                    sqlCall = call.Method.Name.ToLower() + "(" +
                              string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")";
                }
                return(new CompileResult
                {
                    CommandText = sqlCall
                });
            }
            if (expr.NodeType == ExpressionType.Constant)
            {
                var c = (ConstantExpression)expr;
                queryArgs.Add(c.Value);
                return(new CompileResult
                {
                    CommandText = "?",
                    Value = c.Value
                });
            }
            if (expr.NodeType == ExpressionType.Convert)
            {
                var u    = (UnaryExpression)expr;
                var ty   = u.Type;
                var valr = CompileExpr(u.Operand, queryArgs);
                return(new CompileResult
                {
                    CommandText = valr.CommandText,
                    Value = valr.Value != null?ConvertTo(valr.Value, ty) : null
                });
            }
            if (expr.NodeType == ExpressionType.MemberAccess)
            {
                var mem = (MemberExpression)expr;

                if (mem.Expression != null && mem.Expression.NodeType == ExpressionType.Parameter)
                {
                    //
                    // This is a column of our table, output just the column name
                    // Need to translate it if that column name is mapped
                    //
                    var columnName = Table.FindColumnWithPropertyName(mem.Member.Name).Name;
                    return(new CompileResult
                    {
                        CommandText = "\"" + columnName + "\""
                    });
                }
                object obj = null;
                if (mem.Expression != null)
                {
                    var r = CompileExpr(mem.Expression, queryArgs);
                    if (r.Value == null)
                    {
                        throw new NotSupportedException("Member access failed to compile expression");
                    }
                    if (r.CommandText == "?")
                    {
                        queryArgs.RemoveAt(queryArgs.Count - 1);
                    }
                    obj = r.Value;
                }

                //
                // Get the member value
                //
                var val = _sqlitePlatform.ReflectionService.GetMemberValue(obj, expr, mem.Member);

                //
                // Work special magic for enumerables
                //
                if (val != null && val is IEnumerable && !(val is string) && !(val is IEnumerable <byte>))
                {
                    var sb = new StringBuilder();
                    sb.Append("(");
                    var head = "";
                    foreach (var a in (IEnumerable)val)
                    {
                        queryArgs.Add(a);
                        sb.Append(head);
                        sb.Append("?");
                        head = ",";
                    }
                    sb.Append(")");
                    return(new CompileResult
                    {
                        CommandText = sb.ToString(),
                        Value = val
                    });
                }
                queryArgs.Add(val);
                return(new CompileResult
                {
                    CommandText = "?",
                    Value = val
                });
            }
            throw new NotSupportedException("Cannot compile: " + expr.NodeType);
        }
Esempio n. 2
0
        private CompileResult CompileExpr(Expression expr, List <object> queryArgs)
        {
            if (expr == null)
            {
                throw new NotSupportedException("Expression is NULL");
            }
            else if (expr is BinaryExpression)
            {
                var bin = (BinaryExpression)expr;

                var leftr  = CompileExpr(bin.Left, queryArgs);
                var rightr = CompileExpr(bin.Right, queryArgs);

                //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null")
                string text;
                if (leftr.CommandText == "?" && leftr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, rightr);
                }
                else if (rightr.CommandText == "?" && rightr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, leftr);
                }
                else
                {
                    text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")";
                }
                return(new CompileResult {
                    CommandText = text
                });
            }
            else if (expr.NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)expr;
                var args = new CompileResult[call.Arguments.Count];
                var obj  = call.Object != null?CompileExpr(call.Object, queryArgs) : null;

                for (var i = 0; i < args.Length; i++)
                {
                    args[i] = CompileExpr(call.Arguments[i], queryArgs);
                }

                var sqlCall = "";

                if (call.Method.Name == "Like" && args.Length == 2)
                {
                    sqlCall = "(" + args[0].CommandText + " like " + args[1].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 2)
                {
                    sqlCall = "(" + args[1].CommandText + " in " + args[0].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 1)
                {
                    if (call.Object != null && call.Object.Type == typeof(string))
                    {
                        sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + " || '%'))";
                    }
                    else
                    {
                        sqlCall = "(" + args[0].CommandText + " in " + obj.CommandText + ")";
                    }
                }
                else if (call.Method.Name == "StartsWith" && args.Length == 1)
                {
                    sqlCall = "(" + obj.CommandText + " like (" + args[0].CommandText + " || '%'))";
                }
                else if (call.Method.Name == "EndsWith" && args.Length == 1)
                {
                    sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + "))";
                }
                else
                {
                    sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")";
                }
                return(new CompileResult {
                    CommandText = sqlCall
                });
            }
            else if (expr.NodeType == ExpressionType.Constant)
            {
                var c = (ConstantExpression)expr;
                queryArgs.Add(c.Value);
                return(new CompileResult
                {
                    CommandText = "?",
                    Value = c.Value
                });
            }
            else if (expr.NodeType == ExpressionType.Convert)
            {
                var u    = (UnaryExpression)expr;
                var ty   = u.Type;
                var valr = CompileExpr(u.Operand, queryArgs);
                return(new CompileResult
                {
                    CommandText = valr.CommandText,
                    Value = valr.Value != null?ConvertTo(valr.Value, ty) : null
                });
            }
            else if (expr.NodeType == ExpressionType.MemberAccess)
            {
                var mem = (MemberExpression)expr;

                if (mem.Expression.NodeType == ExpressionType.Parameter)
                {
                    //
                    // This is a column of our table, output just the column name
                    // Need to translate it if that column name is mapped
                    //
                    var columnName = Table.FindColumnWithPropertyName(mem.Member.Name).Name;
                    return(new CompileResult {
                        CommandText = "\"" + columnName + "\""
                    });
                }
                else
                {
                    object obj = null;
                    if (mem.Expression != null)
                    {
                        var r = CompileExpr(mem.Expression, queryArgs);
                        if (r.Value == null)
                        {
                            throw new NotSupportedException("Member access failed to compile expression");
                        }
                        if (r.CommandText == "?")
                        {
                            queryArgs.RemoveAt(queryArgs.Count - 1);
                        }
                        obj = r.Value;
                    }

                    //
                    // Get the member value
                    //
                    object val = null;

#if !NETFX_CORE
                    if (mem.Member.MemberType == MemberTypes.Property)
                    {
#else
                    if (mem.Member is PropertyInfo)
                    {
#endif
                        var m = (PropertyInfo)mem.Member;
                        val = m.GetValue(obj, null);
#if !NETFX_CORE
                    }
                    else if (mem.Member.MemberType == MemberTypes.Field)
                    {
#else
                    }
                    else if (mem.Member is FieldInfo)
                    {
#endif
#if SILVERLIGHT
                        val = Expression.Lambda(expr).Compile().DynamicInvoke();
#else
                        var m = (FieldInfo)mem.Member;
                        val = m.GetValue(obj);
#endif
                    }
                    else
                    {
#if !NETFX_CORE
                        throw new NotSupportedException("MemberExpr: " + mem.Member.MemberType.ToString());
#else
                        throw new NotSupportedException("MemberExpr: " + mem.Member.DeclaringType.ToString());
#endif
                    }

                    //
                    // Work special magic for enumerables
                    //
                    if (val != null && val is System.Collections.IEnumerable && !(val is string))
                    {
                        var sb = new System.Text.StringBuilder();
                        sb.Append("(");
                        var head = "";
                        foreach (var a in (System.Collections.IEnumerable)val)
                        {
                            queryArgs.Add(a);
                            sb.Append(head);
                            sb.Append("?");
                            head = ",";
                        }
                        sb.Append(")");
                        return(new CompileResult
                        {
                            CommandText = sb.ToString(),
                            Value = val
                        });
                    }
                    else
                    {
                        queryArgs.Add(val);
                        return(new CompileResult
                        {
                            CommandText = "?",
                            Value = val
                        });
                    }
                }
            }
            throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString());
        }
Esempio n. 3
0
        private CompileResult CompileExpr(Expression expr, List <object> expr_agrs)
        {
            if (expr == null)
            {
                throw new NotSupportedException("Expression is NULL");
            }

            if (expr is BinaryExpression)
            {
                BinaryExpression bin = (BinaryExpression)expr;

                CompileResult leftr  = CompileExpr(bin.Left, expr_agrs);
                CompileResult rightr = CompileExpr(bin.Right, expr_agrs);

                //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null")
                string text;
                if (leftr.CommandText == "?" && leftr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, rightr);
                }
                else if (rightr.CommandText == "?" && rightr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, leftr);
                }
                else
                {
                    text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")";
                }
                return(new CompileResult {
                    CommandText = text
                });
            }

            if (expr.NodeType == ExpressionType.Call)
            {
                MethodCallExpression call = (MethodCallExpression)expr;
                CompileResult[]      args = new CompileResult[call.Arguments.Count];
                CompileResult        obj  = call.Object != null?CompileExpr(call.Object, expr_agrs) : null;

                for (int i = 0; i < args.Length; i++)
                {
                    args[i] = CompileExpr(call.Arguments[i], expr_agrs);
                }

                string sql_call = "";

                if (call.Method.Name == "Like" && args.Length == 2)
                {
                    sql_call = "(" + args[0].CommandText + " LIKE " + args[1].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 2)
                {
                    sql_call = "(" + args[1].CommandText + " IN " + args[0].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 1)
                {
                    if (call.Object != null && call.Object.Type == typeof(string))
                    {
                        sql_call = "(" + obj.CommandText + " LIKE ('%' || " + args[0].CommandText + " || '%'))";
                    }
                    else
                    {
                        sql_call = "(" + args[0].CommandText + " in " + obj.CommandText + ")";
                    }
                }
                else if (call.Method.Name == "StartsWith" && args.Length == 1)
                {
                    sql_call = "(" + obj.CommandText + " LIKE (" + args[0].CommandText + " || '%'))";
                }
                else if (call.Method.Name == "EndsWith" && args.Length == 1)
                {
                    sql_call = "(" + obj.CommandText + " LIKE ('%' || " + args[0].CommandText + "))";
                }
                else if (call.Method.Name == "Equals" && args.Length == 1)
                {
                    sql_call = "(" + obj.CommandText + " = (" + args[0].CommandText + "))";
                }
                else if (call.Method.Name == "ToLower")
                {
                    sql_call = "(LOWER(" + obj.CommandText + "))";
                }
                else if (call.Method.Name == "ToUpper")
                {
                    sql_call = "(UPPER(" + obj.CommandText + "))";
                }
                else
                {
                    sql_call = call.Method.Name.ToLower() + "(" +
                               string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")";
                }

                return(new CompileResult {
                    CommandText = sql_call
                });
            }

            if (expr.NodeType == ExpressionType.Constant)
            {
                ConstantExpression c = (ConstantExpression)expr;
                expr_agrs.Add(c.Value);
                return(new CompileResult
                {
                    CommandText = "?",
                    Value = c.Value
                });
            }

            if (expr.NodeType == ExpressionType.Convert)
            {
                UnaryExpression u    = (UnaryExpression)expr;
                Type            ty   = u.Type;
                CompileResult   valr = CompileExpr(u.Operand, expr_agrs);
                return(new CompileResult
                {
                    CommandText = valr.CommandText,
                    Value = valr.Value != null?ConvertTo(valr.Value, ty) : null
                });
            }

            if (expr.NodeType == ExpressionType.MemberAccess)
            {
                MemberExpression mem = (MemberExpression)expr;

                if (mem.Expression != null && mem.Expression.NodeType == ExpressionType.Parameter)
                {
                    //
                    // This is a column of our table, output just the column name
                    // Need to translate it if that column name is mapped
                    //
                    string columnName = this.Table.FindColumnWithPropertyName(mem.Member.Name).Name;
                    return(new CompileResult {
                        CommandText = "\"" + columnName + "\""
                    });
                }

                object obj = null;
                if (mem.Expression != null)
                {
                    CompileResult r = CompileExpr(mem.Expression, expr_agrs);
                    if (r.Value == null)
                    {
                        throw new NotSupportedException("Member access failed to compile expression");
                    }
                    if (r.CommandText == "?")
                    {
                        expr_agrs.RemoveAt(expr_agrs.Count - 1);
                    }
                    obj = r.Value;
                }

                //
                // Get the member value
                //
                object val = null;

                if (mem.Member.MemberType == MemberTypes.Property)
                {
                    PropertyInfo m = (PropertyInfo)mem.Member;
                    val = m.GetValue(obj, null);
                }
                else if (mem.Member.MemberType == MemberTypes.Field)
                {
                    FieldInfo m = (FieldInfo)mem.Member;
                    val = m.GetValue(obj);
                }
                else
                {
                    throw new NotSupportedException("MemberExpr: " + mem.Member.MemberType);
                }

                //
                // Work special magic for enumerables
                //
                if (val != null && val is IEnumerable && !(val is string) && !(val is IEnumerable <byte>))
                {
                    StringBuilder sb = new StringBuilder();
                    sb.Append("(");
                    string head = "";
                    foreach (object a in (IEnumerable)val)
                    {
                        expr_agrs.Add(a);
                        sb.Append(head);
                        sb.Append("?");
                        head = ",";
                    }

                    sb.Append(")");
                    return(new CompileResult
                    {
                        CommandText = sb.ToString(),
                        Value = val
                    });
                }

                expr_agrs.Add(val);
                return(new CompileResult
                {
                    CommandText = "?",
                    Value = val
                });
            }

            throw new NotSupportedException("Cannot compile: " + expr.NodeType);
        }
Esempio n. 4
0
        CompileResult CompileExpr(Expression expr, List <object> queryArgs)
        {
            if (expr == null)
            {
                throw new NotSupportedException("Expression is NULL");
            }
            else if (expr is BinaryExpression)
            {
                var bin = (BinaryExpression)expr;

                var leftr  = CompileExpr(bin.Left, queryArgs);
                var rightr = CompileExpr(bin.Right, queryArgs);

                var text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")";
                return(new CompileResult {
                    CommandText = text
                });
            }
            else if (expr.NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)expr;
                var args = new CompileResult[call.Arguments.Count];

                for (var i = 0; i < args.Length; i++)
                {
                    args[i] = CompileExpr(call.Arguments[i], queryArgs);
                }

                var sqlCall = "";

                if (call.Method.Name == "Like" && args.Length == 2)
                {
                    sqlCall = "(" + args[0].CommandText + " like " + args[1].CommandText + ")";
                }
                else
                {
                    sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")";
                }
                return(new CompileResult {
                    CommandText = sqlCall
                });
            }
            else if (expr.NodeType == ExpressionType.Constant)
            {
                var c = (ConstantExpression)expr;
                queryArgs.Add(c.Value);
                //Console.WriteLine ("++ constant: {0}", c.Value);
                return(new CompileResult {
                    CommandText = "?", Value = c.Value
                });
            }
            else if (expr.NodeType == ExpressionType.Convert)
            {
                var u    = (UnaryExpression)expr;
                var ty   = u.Type;
                var valr = CompileExpr(u.Operand, queryArgs);
                return(new CompileResult {
                    CommandText = valr.CommandText, Value = valr.Value != null?Convert.ChangeType(valr.Value, ty) : null
                });
            }
            else if (expr.NodeType == ExpressionType.MemberAccess)
            {
                var mem = (MemberExpression)expr;

                if (mem.Expression != null && mem.Expression.NodeType == ExpressionType.Parameter)
                {
                    //
                    // This is a column of our table, output just the column name
                    //
                    return(new CompileResult {
                        CommandText = Quote(mem.Member.Name)
                    });
                }
                else
                {
                    object obj = null;
                    if (mem.Expression != null)
                    {
                        var r = CompileExpr(mem.Expression, queryArgs);
                        if (r.Value == null)
                        {
                            throw new NotSupportedException("Member access failed to compile expression");
                        }
                        if (r.CommandText == "?")
                        {
                            queryArgs.RemoveAt(queryArgs.Count - 1);
                        }
                        obj = r.Value;
                    }

                    if (mem.Member.MemberType == MemberTypes.Property)
                    {
                        var m   = (PropertyInfo)mem.Member;
                        var val = m.GetValue(obj, null);
                        queryArgs.Add(val);
                        //Console.WriteLine ("++ property: {0}", val);
                        return(new CompileResult {
                            CommandText = "?", Value = val
                        });
                    }
                    else if (mem.Member.MemberType == MemberTypes.Field)
                    {
                        var m   = (FieldInfo)mem.Member;
                        var val = m.GetValue(obj);
                        queryArgs.Add(val);
                        //Console.WriteLine ("++ field: {0}", val);
                        return(new CompileResult {
                            CommandText = "?", Value = val
                        });
                    }
                    else
                    {
                        throw new NotSupportedException("MemberExpr: " + mem.Member.MemberType.ToString());
                    }
                }
            }
            throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString());
        }
Esempio n. 5
0
        private CompileResult CompileExpr(Expression expr, List <object> queryArgs)
        {
            if (expr == null)
            {
                throw new NotSupportedException("Expression is NULL");
            }
            else if (expr is BinaryExpression)
            {
                var bin = (BinaryExpression)expr;

                // VB turns 'x=="foo"' into 'CompareString(x,"foo",true/false)==0', so we need to unwrap it
                // http://blogs.msdn.com/b/vbteam/archive/2007/09/18/vb-expression-trees-string-comparisons.aspx
                if (bin.Left.NodeType == ExpressionType.Call)
                {
                    var call = (MethodCallExpression)bin.Left;
                    if (call.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" &&
                        call.Method.Name == "CompareString")
                    {
                        bin = Expression.MakeBinary(bin.NodeType, call.Arguments [0], call.Arguments [1]);
                    }
                }


                var leftr  = CompileExpr(bin.Left, queryArgs);
                var rightr = CompileExpr(bin.Right, queryArgs);

                //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null")
                string text;
                if (leftr.CommandText == "?" && leftr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, rightr);
                }
                else if (rightr.CommandText == "?" && rightr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, leftr);
                }
                else
                {
                    text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")";
                }
                return(new CompileResult {
                    CommandText = text
                });
            }
            else if (expr.NodeType == ExpressionType.Not)
            {
                var    operandExpr = ((UnaryExpression)expr).Operand;
                var    opr         = CompileExpr(operandExpr, queryArgs);
                object val         = opr.Value;
                if (val is bool)
                {
                    val = !((bool)val);
                }
                return(new CompileResult {
                    CommandText = "NOT(" + opr.CommandText + ")",
                    Value = val
                });
            }
            else if (expr.NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)expr;
                var args = new CompileResult [call.Arguments.Count];
                var obj  = call.Object != null?CompileExpr(call.Object, queryArgs) : null;

                for (var i = 0; i < args.Length; i++)
                {
                    args [i] = CompileExpr(call.Arguments [i], queryArgs);
                }

                var sqlCall = "";

                if (call.Method.Name == "Like" && args.Length == 2)
                {
                    sqlCall = "(" + args [0].CommandText + " like " + args [1].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 2)
                {
                    sqlCall = "(" + args [1].CommandText + " in " + args [0].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 1)
                {
                    if (call.Object != null && call.Object.Type == typeof(string))
                    {
                        sqlCall = "( instr(" + obj.CommandText + "," + args [0].CommandText + ") >0 )";
                    }
                    else
                    {
                        sqlCall = "(" + args [0].CommandText + " in " + obj.CommandText + ")";
                    }
                }
                else if (call.Method.Name == "StartsWith" && args.Length >= 1)
                {
                    var startsWithCmpOp = StringComparison.CurrentCulture;
                    if (args.Length == 2)
                    {
                        startsWithCmpOp = (StringComparison)args [1].Value;
                    }
                    switch (startsWithCmpOp)
                    {
                    case StringComparison.Ordinal:
                    case StringComparison.CurrentCulture:
                        sqlCall = "( substr(" + obj.CommandText + ", 1, " + args [0].Value.ToString().Length + ") =  " + args [0].CommandText + ")";
                        break;

                    case StringComparison.OrdinalIgnoreCase:
                    case StringComparison.CurrentCultureIgnoreCase:
                        sqlCall = "(" + obj.CommandText + " like (" + args [0].CommandText + " || '%'))";
                        break;
                    }
                }
                else if (call.Method.Name == "EndsWith" && args.Length >= 1)
                {
                    var endsWithCmpOp = StringComparison.CurrentCulture;
                    if (args.Length == 2)
                    {
                        endsWithCmpOp = (StringComparison)args [1].Value;
                    }
                    switch (endsWithCmpOp)
                    {
                    case StringComparison.Ordinal:
                    case StringComparison.CurrentCulture:
                        sqlCall = "( substr(" + obj.CommandText + ", length(" + obj.CommandText + ") - " + args [0].Value.ToString().Length + "+1, " + args [0].Value.ToString().Length + ") =  " + args [0].CommandText + ")";
                        break;

                    case StringComparison.OrdinalIgnoreCase:
                    case StringComparison.CurrentCultureIgnoreCase:
                        sqlCall = "(" + obj.CommandText + " like ('%' || " + args [0].CommandText + "))";
                        break;
                    }
                }
                else if (call.Method.Name == "Equals" && args.Length == 1)
                {
                    sqlCall = "(" + obj.CommandText + " = (" + args [0].CommandText + "))";
                }
                else if (call.Method.Name == "ToLower")
                {
                    sqlCall = "(lower(" + obj.CommandText + "))";
                }
                else if (call.Method.Name == "ToUpper")
                {
                    sqlCall = "(upper(" + obj.CommandText + "))";
                }
                else if (call.Method.Name == "Replace" && args.Length == 2)
                {
                    sqlCall = "(replace(" + obj.CommandText + "," + args [0].CommandText + "," + args [1].CommandText + "))";
                }
                else
                {
                    sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")";
                }
                return(new CompileResult {
                    CommandText = sqlCall
                });
            }
            else if (expr.NodeType == ExpressionType.Constant)
            {
                var c = (ConstantExpression)expr;
                queryArgs.Add(c.Value);
                return(new CompileResult {
                    CommandText = "?",
                    Value = c.Value
                });
            }
            else if (expr.NodeType == ExpressionType.Convert)
            {
                var u    = (UnaryExpression)expr;
                var ty   = u.Type;
                var valr = CompileExpr(u.Operand, queryArgs);
                return(new CompileResult {
                    CommandText = valr.CommandText,
                    Value = valr.Value != null?ConvertTo(valr.Value, ty) : null
                });
            }
            else if (expr.NodeType == ExpressionType.MemberAccess)
            {
                var mem = (MemberExpression)expr;

                var paramExpr = mem.Expression as ParameterExpression;
                if (paramExpr == null)
                {
                    var convert = mem.Expression as UnaryExpression;
                    if (convert != null && convert.NodeType == ExpressionType.Convert)
                    {
                        paramExpr = convert.Operand as ParameterExpression;
                    }
                }

                if (paramExpr != null)
                {
                    //
                    // This is a column of our table, output just the column name
                    // Need to translate it if that column name is mapped
                    //
                    var columnName = Table.FindColumnWithPropertyName(mem.Member.Name).Name;
                    return(new CompileResult {
                        CommandText = "\"" + columnName + "\""
                    });
                }
                else
                {
                    object obj = null;
                    if (mem.Expression != null)
                    {
                        var r = CompileExpr(mem.Expression, queryArgs);
                        if (r.Value == null)
                        {
                            throw new NotSupportedException("Member access failed to compile expression");
                        }
                        if (r.CommandText == "?")
                        {
                            queryArgs.RemoveAt(queryArgs.Count - 1);
                        }
                        obj = r.Value;
                    }

                    //
                    // Get the member value
                    //
                    object val = null;

                    if (mem.Member is PropertyInfo)
                    {
                        var m = (PropertyInfo)mem.Member;
                        val = m.GetValue(obj, null);
                    }
                    else if (mem.Member is FieldInfo)
                    {
                        var m = (FieldInfo)mem.Member;
                        val = m.GetValue(obj);
                    }
                    else
                    {
                        throw new NotSupportedException("MemberExpr: " + mem.Member.GetType());
                    }

                    //
                    // Work special magic for enumerables
                    //
                    if (val != null && val is System.Collections.IEnumerable && !(val is string) && !(val is System.Collections.Generic.IEnumerable <byte>))
                    {
                        var sb = new System.Text.StringBuilder();
                        sb.Append("(");
                        var head = "";
                        foreach (var a in (System.Collections.IEnumerable)val)
                        {
                            queryArgs.Add(a);
                            sb.Append(head);
                            sb.Append("?");
                            head = ",";
                        }
                        sb.Append(")");
                        return(new CompileResult {
                            CommandText = sb.ToString(),
                            Value = val
                        });
                    }
                    else
                    {
                        queryArgs.Add(val);
                        return(new CompileResult {
                            CommandText = "?",
                            Value = val
                        });
                    }
                }
            }
            throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString());
        }
Esempio n. 6
0
        internal CompileResult CompileExpr(Expression expr, List <object> queryArgs, List <Condition> conditions)
        {
            if (expr == null)
            {
                throw new NotSupportedException("Expression is NULL");
            }
            else if (expr is BinaryExpression)
            {
                var bin = (BinaryExpression)expr;

                // VB turns 'x=="foo"' into 'CompareString(x,"foo",true/false)==0', so we need to unwrap it
                // http://blogs.msdn.com/b/vbteam/archive/2007/09/18/vb-expression-trees-string-comparisons.aspx
                if (bin.Left.NodeType == ExpressionType.Call)
                {
                    var call = (MethodCallExpression)bin.Left;
                    if (call.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" &&
                        call.Method.Name == "CompareString")
                    {
                        bin = Expression.MakeBinary(bin.NodeType, call.Arguments[0], call.Arguments[1]);
                    }
                }

                var leftr  = CompileExpr(bin.Left, queryArgs, conditions);
                var rightr = CompileExpr(bin.Right, queryArgs, conditions);

                if (leftr.CurrentCondition?.IsComplete ?? false)
                {
                    conditions.Add(leftr.CurrentCondition);
                }
                if (rightr.CurrentCondition?.IsComplete ?? false)
                {
                    conditions.Add(rightr.CurrentCondition);
                }
                if (leftr.CurrentCondition != null && !leftr.CurrentCondition.IsComplete)
                {
                    Condition joinedCondition = new Condition(leftr.CurrentCondition, rightr.CurrentCondition);
                    if (joinedCondition.IsComplete)
                    {
                        conditions.Add(joinedCondition);
                        conditions.Remove(rightr.CurrentCondition);
                        conditions.Remove(leftr.CurrentCondition);
                    }
                }

                //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null")
                string text;
                if (leftr.CommandText == "?" && leftr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, leftr, conditions);
                    //conditions.Insert(0, leftr.CurrentCondition);
                }
                else if (rightr.CommandText == "?" && rightr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, leftr, conditions);
                }
                else
                {
                    if ((rightr.CommandText == "?") && this is SQLServerTableQuery <T> )
                    {
                        if (string.IsNullOrEmpty(rightr.CurrentCondition.ColumnName))
                        {
                            var constCondtion = new Condition($"Constant{Guid.NewGuid():N}", rightr.CurrentCondition.Value);
                            conditions.Insert(0, constCondtion);
                            rightr.CommandText = "@" + constCondtion.ColumnName;
                        }
                        else
                        {
                            rightr.CommandText = "@" + leftr.CurrentCondition.ColumnName.Replace("\"", "");
                        }
                    }

                    if ((leftr.CommandText == "?") && this is SQLServerTableQuery <T> )
                    {
                        if (leftr.Value is bool)
                        {
                            leftr.CommandText = "@" + leftr.CurrentCondition.ColumnName.Replace("\"", "") + "=1";
                        }
                        else
                        {
                            leftr.CommandText = "@" + leftr.CurrentCondition.ColumnName.Replace("\"", "");
                        }
                    }

                    var _operator = GetSqlName(bin);
                    text = "(" + leftr.CommandText + " " + _operator + " " + rightr.CommandText + " )";
                }

                leftr.CurrentCondition  = null;
                rightr.CurrentCondition = null;
                return(new CompileResult {
                    CommandText = text
                });
            }
            else if (expr.NodeType == ExpressionType.Not)
            {
                var    operandExpr = ((UnaryExpression)expr).Operand;
                var    opr         = CompileExpr(operandExpr, queryArgs, conditions);
                object val         = opr.Value;
                if (val is bool)
                {
                    val = !((bool)val);
                }

                if (this is SQLServerTableQuery <T> )
                {
                    if (opr.CommandText.EndsWith("=1"))
                    {
                        opr.CommandText = opr.CommandText.Replace("=1", "");
                    }
                    Condition condition = null;
                    if (val is not null)
                    {
                        condition = new Condition(opr.CommandText, val);
                    }
                    return(new CompileResult
                    {
                        CommandText = "(" + opr.CommandText + "=0)",
                        Value = val,
                        CurrentCondition = condition
                    });
                }
                else
                {
                    Condition condition = new Condition(opr.CommandText, val);
                    return(new CompileResult
                    {
                        CommandText = "NOT(" + opr.CommandText + ")",
                        Value = val,
                        CurrentCondition = condition
                    });
                }
            }
            else if (expr.NodeType == ExpressionType.Call)
            {
                Condition CurrentCondition = null;
                var       call             = (MethodCallExpression)expr;
                var       args             = new CompileResult[call.Arguments.Count];
                var       obj = call.Object != null?CompileExpr(call.Object, queryArgs, conditions) : null;

                for (var i = 0; i < args.Length; i++)
                {
                    args[i] = CompileExpr(call.Arguments[i], queryArgs, conditions);
                }

                var sqlCall = "";

                if (call.Method.Name == "Like" && args.Length == 2)
                {
                    sqlCall = "(" + args[0].CommandText + " like " + args[1].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 2)
                {
                    sqlCall = "(" + args[1].CommandText + " in " + args[0].CommandText + ")";
                }
                else if (call.Method.Name == "Contains" && args.Length == 1)
                {
                    if (call.Object != null && call.Object.Type == typeof(string))
                    {
                        if (this.Connection is SQLServerConnection)
                        {
                            sqlCall = "( (" + obj.CommandText + "LIKE '%'+@" + args[0].CurrentCondition.ColumnName + "+'%') )";
                        }
                        else
                        {
                            sqlCall = "(" + obj.CommandText + " LIKE '%'||" + args[0].CommandText + "||'%')";
                        }
                    }
                    else
                    {
                        if (this.Connection is SQLServerConnection)
                        {
                            sqlCall = "(@" + args[0].CurrentCondition.ColumnName + " in " + obj.CommandText + ")";
                        }
                        else
                        {
                            sqlCall = "(" + args[0].CommandText + " in " + obj.CommandText + ")";
                        }
                    }

                    CurrentCondition = args[0].CurrentCondition;
                }
                else if (call.Method.Name == "StartsWith" && args.Length >= 1)
                {
                    var startsWithCmpOp = StringComparison.CurrentCulture;
                    if (args.Length == 2)
                    {
                        startsWithCmpOp = (StringComparison)args[1].Value;
                    }
                    switch (startsWithCmpOp)
                    {
                    case StringComparison.Ordinal:
                    case StringComparison.CurrentCulture:
                        sqlCall = "( substr(" + obj.CommandText + ", 1, " + args[0].Value.ToString().Length + ") =  " + args[0].CommandText + ")";
                        break;

                    case StringComparison.OrdinalIgnoreCase:
                    case StringComparison.CurrentCultureIgnoreCase:
                        sqlCall = "(" + obj.CommandText + " like (" + args[0].CommandText + " || '%'))";
                        break;
                    }
                }
                else if (call.Method.Name == "EndsWith" && args.Length >= 1)
                {
                    var endsWithCmpOp = StringComparison.CurrentCulture;
                    if (args.Length == 2)
                    {
                        endsWithCmpOp = (StringComparison)args[1].Value;
                    }
                    switch (endsWithCmpOp)
                    {
                    case StringComparison.Ordinal:
                    case StringComparison.CurrentCulture:
                        sqlCall = "( substr(" + obj.CommandText + ", length(" + obj.CommandText + ") - " + args[0].Value.ToString().Length + "+1, " + args[0].Value.ToString().Length + ") =  " + args[0].CommandText + ")";
                        break;

                    case StringComparison.OrdinalIgnoreCase:
                    case StringComparison.CurrentCultureIgnoreCase:
                        sqlCall = "(" + obj.CommandText + " like ('%' || " + args[0].CommandText + "))";
                        break;
                    }
                }
                else if (call.Method.Name == "Equals" && args.Length == 1)
                {
                    sqlCall = "(" + obj.CommandText + " = (" + args[0].CommandText + "))";
                }
                else if (call.Method.Name == "ToLower")
                {
                    sqlCall = "(lower(" + obj.CommandText + "))";
                }
                else if (call.Method.Name == "ToUpper")
                {
                    sqlCall = "(upper(" + obj.CommandText + "))";
                }
                else if (call.Method.Name == "Replace" && args.Length == 2)
                {
                    sqlCall = "(replace(" + obj.CommandText + "," + args[0].CommandText + "," + args[1].CommandText + "))";
                }
                else if (call.Method.Name == "IsNullOrEmpty" && args.Length == 1)
                {
                    if (this.Connection is SQLServerConnection)
                    {
                        sqlCall = "(@" + args[0].CurrentCondition.ColumnName + " is null or @" + args[0].CurrentCondition.ColumnName + " ='' )";
                    }
                    else
                    {
                        sqlCall = "( IFNULL(" + args[0].CommandText + ",'')='' )";
                    }

                    CurrentCondition = args[0].CurrentCondition;
                }
                else
                {
                    sqlCall = call.Method.Name.ToLower() + "(" + string.Join(",", args.Select(a => a.CommandText).ToArray()) + ")";
                }
                return(new CompileResult {
                    CommandText = sqlCall, CurrentCondition = CurrentCondition
                });
            }
            else if (expr.NodeType == ExpressionType.Constant)
            {
                var c = (ConstantExpression)expr;
                queryArgs.Add(c.Value);
                //var condition = new Condition(c.Value);
                //conditions.Add(condition);
                return(new CompileResult
                {
                    CommandText = "?",
                    Value = c.Value,
                    CurrentCondition = new Condition(c.Value)
                });
            }
            else if (expr.NodeType == ExpressionType.Convert)
            {
                var u    = (UnaryExpression)expr;
                var ty   = u.Type;
                var valr = CompileExpr(u.Operand, queryArgs, conditions);

                var truvalue = valr.Value != null?ConvertTo(valr.Value, ty) : null;

                if (truvalue is int enuTruvalue)
                {
                    if (u.Operand.Type.IsEnum)
                    {
                        if (u.Operand.Type.IsDefined(typeof(StoreAsTextAttribute), false))
                        {
                            string text_enum = Enum.GetName(u.Operand.Type, enuTruvalue);
                            if (!string.IsNullOrEmpty(text_enum))
                            {
                                truvalue = text_enum;
                            }
                        }
                    }
                }
                if ((ty == typeof(Guid) || ty == typeof(Guid?)) && truvalue is null)
                {
                    return(new CompileResult
                    {
                        CommandText = valr.CommandText,
                        Value = null,
                        CurrentCondition = new Condition(valr.CommandText)
                    });
                }
                return(new CompileResult
                {
                    CommandText = valr.CommandText,
                    Value = truvalue,
                    CurrentCondition = new Condition(valr.CommandText.Replace("\"", String.Empty), truvalue)
                });
            }
            else if (expr.NodeType == ExpressionType.MemberAccess)
            {
                var mem = (MemberExpression)expr;

                var paramExpr = mem.Expression as ParameterExpression;
                if (paramExpr == null)
                {
                    var convert = mem.Expression as UnaryExpression;
                    if (convert != null && convert.NodeType == ExpressionType.Convert)
                    {
                        paramExpr = convert.Operand as ParameterExpression;
                    }
                }

                if (paramExpr != null)
                {
                    //
                    // This is a column of our table, output just the column name
                    // Need to translate it if that column name is mapped
                    //
                    var column = Table.FindColumnWithPropertyName(mem.Member.Name);
                    if (column is null)
                    {
                        throw new KeyNotFoundException($"La columna {mem.Member.Name} no existe en la tabla {Table.TableName}");
                    }

                    var columnName = column.Name;
                    if (column.ColumnType == typeof(bool) && this.Connection is SQLServerConnection)
                    {
                        return(new CompileResult
                        {
                            CommandText = "\"" + columnName + "\"=1",
                            CurrentCondition = new Condition(columnName)
                        });
                    }
                    return(new CompileResult
                    {
                        CommandText = "\"" + columnName + "\"",
                        CurrentCondition = new Condition(columnName)
                    });
                }
                else
                {
                    object obj = null;
                    if (mem.Expression != null)
                    {
                        var r = CompileExpr(mem.Expression, queryArgs, conditions);
                        if (r.Value == null)
                        {
                            throw new NotSupportedException("Member access failed to compile expression");
                        }
                        if (r.CommandText == "?")
                        {
                            int remove_index = queryArgs.Count - 1;
                            queryArgs.RemoveAt(remove_index);
                            //conditions.RemoveAt(remove_index);
                        }
                        obj = r.Value;
                    }

                    //
                    // Get the member value
                    //
                    object val       = null;
                    string fieldname = string.Empty;
                    if (mem.Member is PropertyInfo)
                    {
                        var m = (PropertyInfo)mem.Member;
                        val       = m.GetValue(obj, null);
                        fieldname = m.Name;
                    }
                    else if (mem.Member is FieldInfo)
                    {
                        var m = (FieldInfo)mem.Member;
                        val       = m.GetValue(obj);
                        fieldname = m.Name;
                    }
                    else
                    {
                        throw new NotSupportedException("MemberExpr: " + mem.Member.GetType());
                    }

                    //
                    // Work special magic for enumerables
                    //
                    if (val != null && val is System.Collections.IEnumerable && !(val is string) && !(val is System.Collections.Generic.IEnumerable <byte>))
                    {
                        var sb = new System.Text.StringBuilder();
                        sb.Append("(");
                        var head = "";
                        foreach (var a in (System.Collections.IEnumerable)val)
                        {
                            queryArgs.Add(a);
                            sb.Append(head);
                            sb.Append("?");
                            head = ",";
                        }
                        sb.Append(")");
                        return(new CompileResult
                        {
                            CommandText = sb.ToString(),
                            Value = val
                        });
                    }
                    else
                    {
                        queryArgs.Add(val);
                        return(new CompileResult
                        {
                            CommandText = "?",
                            Value = val,
                            CurrentCondition = new Condition(fieldname, val)
                        });
                    }
                }
            }
            throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString());
        }
Esempio n. 7
0
        private CompileResult CompileExpr(Expression expr, List <object> queryArgs)
        {
            if (expr == null)
            {
                throw new NotSupportedException("Expression is NULL");
            }

            if (expr is BinaryExpression)
            {
                var bin = (BinaryExpression)expr;

                CompileResult leftr  = CompileExpr(bin.Left, queryArgs);
                CompileResult rightr = CompileExpr(bin.Right, queryArgs);

                //If either side is a parameter and is null, then handle the other side specially (for "is null"/"is not null")
                string text;
                if (leftr.CommandText == "?" && leftr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, rightr);
                }
                else if (rightr.CommandText == "?" && rightr.Value == null)
                {
                    text = CompileNullBinaryExpression(bin, leftr);
                }
                else
                {
                    text = "(" + leftr.CommandText + " " + GetSqlName(bin) + " " + rightr.CommandText + ")";
                }
                return(new CompileResult {
                    CommandText = text
                });
            }
            else if (expr.NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)expr;
                var args = new CompileResult[call.Arguments.Count];
                var obj  = call.Object != null?CompileExpr(call.Object, queryArgs) : null;

                string methodName = call.Method.Name;
                string sqlCall    = string.Empty;

                for (int i = 0; i < args.Length; i++)
                {
                    args[i] = CompileExpr(call.Arguments[i], queryArgs);
                }

                if (methodName == "Contains")
                {
                    if (args.Length == 1)
                    {
                        // string.Contains("xxx") or list.Contains(x)
                        if (call.Object != null && call.Object.Type == typeof(string))
                        {
                            sqlCall = "({0} like ('%' || {1} || '%'))";
                        }
                        else
                        {
                            sqlCall = "({1} in {0})";
                        }

                        sqlCall = string.Format(sqlCall, obj.CommandText, args[0].CommandText);
                    }
                    else if (args.Length == 2)
                    {
                        sqlCall = string.Format("({0} in {1})", args[1].CommandText, args[0].CommandText);
                    }
                }
                else if (methodName == "StartsWith" || methodName == "EndsWith")
                {
                    if (args.Length == 1)
                    {
                        if (methodName == "StartsWith")
                        {
                            sqlCall = "({0} like ({1} || '%'))";
                        }
                        else if (methodName == "EndsWith")
                        {
                            sqlCall = "({0} like ('%' || {1}))";
                        }

                        sqlCall = string.Format(sqlCall, obj.CommandText, args[0].CommandText);
                    }
                }
                else if (methodName == "Matches" && args.Length == 2)
                {
                    sqlCall = "({0} match {1})";
                    sqlCall = string.Format(sqlCall, args[0].CommandText, args[1].CommandText);
                }
                else
                {
                    var arguments = string.Join(",", args.Select(a => a.CommandText).ToArray());
                    sqlCall = string.Format("{0}({1})", methodName.ToLower(), arguments);
                }

                return(new CompileResult {
                    CommandText = sqlCall
                });
            }
            else if (expr.NodeType == ExpressionType.Constant)
            {
                var c = (ConstantExpression)expr;
                queryArgs.Add(c.Value);
                return(new CompileResult
                {
                    CommandText = "?",
                    Value = c.Value
                });
            }
            else if (expr.NodeType == ExpressionType.Convert)
            {
                var           u    = (UnaryExpression)expr;
                Type          ty   = u.Type;
                CompileResult valr = CompileExpr(u.Operand, queryArgs);

                var underlyingType = Nullable.GetUnderlyingType(ty);
                if (underlyingType != null)
                {
                    ty = underlyingType;
                }

                return(new CompileResult
                {
                    CommandText = valr.CommandText,
                    Value = valr.Value != null?Convert.ChangeType(valr.Value, ty, null) : null
                });
            }
            else if (expr.NodeType == ExpressionType.MemberAccess)
            {
                var mem = (MemberExpression)expr;

                if (mem.Expression.NodeType == ExpressionType.Parameter)
                {
                    //
                    // This is a column of our table, output just the column name
                    //
                    return(new CompileResult {
                        CommandText = "\"" + OrmHelper.GetColumnName(mem.Member) + "\""
                    });
                }
                else
                {
                    object obj = null;
                    if (mem.Expression != null)
                    {
                        CompileResult r = CompileExpr(mem.Expression, queryArgs);
                        if (r.Value == null)
                        {
                            throw new NotSupportedException("Member access failed to compile expression");
                        }
                        if (r.CommandText == "?")
                        {
                            queryArgs.RemoveAt(queryArgs.Count - 1);
                        }
                        obj = r.Value;
                    }

                    //
                    // Get the member value
                    //
                    object val = null;

                    if (mem.Member is PropertyInfo)
                    {
                        var m = (PropertyInfo)mem.Member;
                        val = m.GetValue(obj, null);
                    }
                    else if (mem.Member is FieldInfo)
                    {
#if SILVERLIGHT
                        val = Expression.Lambda(expr).Compile().DynamicInvoke();
#else
                        var m = (FieldInfo)mem.Member;
                        val = m.GetValue(obj);
#endif
                    }
                    else
                    {
                        throw new NotSupportedException("MemberExpr: " + mem.Member.GetType().Name);
                    }

                    //
                    // Work special magic for enumerables
                    //
                    if (val != null && val is IEnumerable && !(val is string))
                    {
                        var sb = new StringBuilder();
                        sb.Append("(");
                        string head = "";
                        foreach (object a in (IEnumerable)val)
                        {
                            queryArgs.Add(a);
                            sb.Append(head);
                            sb.Append("?");
                            head = ",";
                        }
                        sb.Append(")");
                        return(new CompileResult
                        {
                            CommandText = sb.ToString(),
                            Value = val
                        });
                    }
                    else
                    {
                        queryArgs.Add(val);
                        return(new CompileResult
                        {
                            CommandText = "?",
                            Value = val
                        });
                    }
                }
            }
            throw new NotSupportedException("Cannot compile: " + expr.NodeType.ToString());
        }