private string IncludeAlias(Data.ConditionCollection cc, MemberExpression lExp, string alias)
        {
            var innerExp = lExp.Expression as MemberExpression;

            if (innerExp != null)
            {
                alias = IncludeAlias(cc, innerExp, alias);
            }

            string newAlias = lExp.Member.Name.ToLower() + random.Next(1000, 9999).ToString();

            cc.Include(alias, lExp.Member.Name, newAlias, Data.JoinMode.LeftJoin);

            return(newAlias);
        }
        private void ReadWhereExpressions(Tenor.Data.ConditionCollection cc, Expression ex, bool not, string alias)
        {
            switch (ex.NodeType)
            {
            case ExpressionType.Quote:
            {
                UnaryExpression une = ex as UnaryExpression;
                if (une.IsLifted || une.IsLiftedToNull)
                {
                    throw new NotImplementedException();
                }

                ReadWhereExpressions(cc, une.Operand, not, alias);
            }
            break;

            case ExpressionType.Lambda:
            {
                LambdaExpression lex = ex as LambdaExpression;
                //TODO: Should we check parameters?
                ReadWhereExpressions(cc, lex.Body, not, alias);
            }
            break;

            case ExpressionType.Not:
            {
                UnaryExpression une = ex as UnaryExpression;
                if (une.IsLifted || une.IsLiftedToNull)
                {
                    throw new NotImplementedException();
                }

                ReadWhereExpressions(cc, une.Operand, !not, alias);
            }
            break;

            case ExpressionType.And:
            case ExpressionType.AndAlso:
            {
                BinaryExpression andBinary = ex as BinaryExpression;

                Tenor.Data.ConditionCollection newCc = new Tenor.Data.ConditionCollection();

                ReadWhereExpressions(newCc, andBinary.Left, not, alias);
                newCc.Add(Tenor.Data.LogicalOperator.And);
                ReadWhereExpressions(newCc, andBinary.Right, not, alias);

                if (cc.Count > 0 && cc[cc.Count - 1].GetType() != typeof(Tenor.Data.LogicalOperator))
                {
                    cc.Add(Tenor.Data.LogicalOperator.And);
                }
                cc.Add(newCc);
            }
            break;

            case ExpressionType.Or:
            case ExpressionType.OrElse:
            {
                BinaryExpression andBinary = ex as BinaryExpression;

                Tenor.Data.ConditionCollection newCc = new Tenor.Data.ConditionCollection();

                ReadWhereExpressions(newCc, andBinary.Left, not, alias);
                newCc.Add(Tenor.Data.LogicalOperator.Or);
                ReadWhereExpressions(newCc, andBinary.Right, not, alias);

                if (cc.Count > 0 && cc[cc.Count - 1].GetType() != typeof(Tenor.Data.LogicalOperator))
                {
                    cc.Add(Tenor.Data.LogicalOperator.And);
                }
                cc.Add(newCc);
            }
            break;

            case ExpressionType.Equal:
            case ExpressionType.NotEqual:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
            {
                BinaryExpression bex = ex as BinaryExpression;

                bool lower = false, upper = false;
                if (bex.Left.NodeType == ExpressionType.Call)
                {
                    var call = (bex.Left as MethodCallExpression);
                    lower = (call.Method.Name == "ToLower");
                    upper = (call.Method.Name == "ToUpper");
                }
                MemberExpression left = ReadOperand(bex, false) as MemberExpression;



                bool       invertOperator = false;
                Expression right          = ReadOperand(bex, true, ref invertOperator);

                if (ex.NodeType != ExpressionType.Equal && ex.NodeType != ExpressionType.NotEqual && invertOperator)
                {
                    not = !not;
                }


                //check if we need another alias
                if (left.Expression != null && left.Expression is MemberExpression)
                {
                    MemberExpression lExp = (MemberExpression)left.Expression;
                    if (lExp.Member.MemberType == MemberTypes.Property)
                    {
                        alias = IncludeAlias(cc, lExp, alias);
                    }
                }

                Tenor.Data.CompareOperator op = Tenor.Data.CompareOperator.Equal;
                if (ex.NodeType == ExpressionType.Equal && !not)
                {
                    op = Tenor.Data.CompareOperator.Equal;
                }
                else if (ex.NodeType == ExpressionType.Equal && not)
                {
                    op = Tenor.Data.CompareOperator.NotEqual;
                }
                else if (ex.NodeType == ExpressionType.NotEqual && !not)
                {
                    op = Tenor.Data.CompareOperator.NotEqual;
                }
                else if (ex.NodeType == ExpressionType.NotEqual && not)
                {
                    op = Tenor.Data.CompareOperator.Equal;
                }
                else if (ex.NodeType == ExpressionType.GreaterThan && !not)
                {
                    op = Tenor.Data.CompareOperator.GreaterThan;
                }
                else if (ex.NodeType == ExpressionType.GreaterThan && not)
                {
                    op = Tenor.Data.CompareOperator.LessThan;
                }
                else if (ex.NodeType == ExpressionType.LessThan && !not)
                {
                    op = Tenor.Data.CompareOperator.LessThan;
                }
                else if (ex.NodeType == ExpressionType.LessThan && not)
                {
                    op = Tenor.Data.CompareOperator.GreaterThan;
                }
                else if (ex.NodeType == ExpressionType.GreaterThanOrEqual && !not)
                {
                    op = Tenor.Data.CompareOperator.GreaterThanOrEqual;
                }
                else if (ex.NodeType == ExpressionType.GreaterThanOrEqual && not)
                {
                    op = Tenor.Data.CompareOperator.LessThanOrEqual;
                }
                else if (ex.NodeType == ExpressionType.LessThanOrEqual && !not)
                {
                    op = Tenor.Data.CompareOperator.LessThanOrEqual;
                }
                else if (ex.NodeType == ExpressionType.LessThanOrEqual && not)
                {
                    op = Tenor.Data.CompareOperator.GreaterThanOrEqual;
                }

                if (op == Data.CompareOperator.Equal)
                {
                    if (upper)
                    {
                        op = Tenor.Data.CompareOperator.EqualUpper;
                    }
                    else if (lower)
                    {
                        op = Tenor.Data.CompareOperator.EqualLower;
                    }
                }
                else if (op == Data.CompareOperator.NotEqual)
                {
                    if (upper)
                    {
                        op = Tenor.Data.CompareOperator.NotEqualUpper;
                    }
                    else if (lower)
                    {
                        op = Tenor.Data.CompareOperator.NotEqualLower;
                    }
                }

                if (cc.Count > 0 && !(cc[cc.Count - 1] is Tenor.Data.LogicalOperator))
                {
                    cc.Add(Data.LogicalOperator.And);
                }
                cc.Add(left.Member.Name, FindValue(right), op, alias);
            }
            break;

            case ExpressionType.MemberAccess:
            {
                MemberExpression mex = ex as MemberExpression;
                if (mex.Type != typeof(bool) && (!mex.Type.IsGenericType || mex.Type != typeof(bool?)))
                {
                    throw new InvalidOperationException("Invalid lambda expression");
                }

                Tenor.Data.CompareOperator op = Tenor.Data.CompareOperator.Equal;
                if (not)
                {
                    op = Tenor.Data.CompareOperator.NotEqual;
                }

                if (cc.Count > 0 && cc[cc.Count - 1].GetType() != typeof(Tenor.Data.LogicalOperator))
                {
                    cc.Add(Tenor.Data.LogicalOperator.And);
                }
                cc.Add(mex.Member.Name, true, op, alias);
            }
            break;

            case ExpressionType.Call:
            {
                MethodCallExpression mce = (MethodCallExpression)ex;

                switch (mce.Method.Name)
                {
                case "Contains":
                case "StartsWith":
                case "EndsWith":
                {
                    MemberExpression member =
                        (mce.Object != null ? mce.Object : mce.Arguments[0]) as MemberExpression;

                    MemberExpression property =
                        (mce.Object != null ? mce.Arguments[0] : mce.Arguments[1]) as MemberExpression;

                    MethodCallExpression methodCall =
                        (mce.Object != null ? mce.Arguments[0] : mce.Arguments[1]) as MethodCallExpression;

                    if (mce.Method.Name == "Contains" && member.Type != typeof(string))
                    {
                        // In
                        Tenor.Data.ConditionCollection inValues = new Data.ConditionCollection();
                        IList list = FindValue(member) as IList;
                        foreach (object v in list)
                        {
                            if (inValues.Count > 0)
                            {
                                inValues.Add(Data.LogicalOperator.Or);
                            }
                            inValues.Add(property.Member.Name, v, Data.CompareOperator.Equal, alias);
                        }
                        if (inValues.Count > 0)
                        {
                            cc.Add(inValues);
                        }
                    }
                    else if (member.Type == typeof(string))
                    {
                        //this will generate a like expression

                        string str = property != null?
                                     FindValue(property) as string :
                                     FindValue(methodCall) as string;

                        if (mce.Method.Name == "StartsWith")
                        {
                            str = string.Format("{0}%", str);
                        }
                        else if (mce.Method.Name == "EndsWith")
                        {
                            str = string.Format("%{0}", str);
                        }
                        else if (mce.Method.Name == "Contains")
                        {
                            str = string.Format("%{0}%", str);
                        }

                        Tenor.Data.CompareOperator op = Tenor.Data.CompareOperator.Like;
                        if (not)
                        {
                            op = Tenor.Data.CompareOperator.NotLike;
                        }

                        cc.Add(member.Member.Name, str, op, alias);
                    }
                    else
                    {
                        throw new NotImplementedException(string.Format("{0} not implemented with current parameters.", mce.Method.Name));
                    }
                }
                break;

                case "Any":
                {
                    //here we will join.

                    MemberExpression member   = mce.Arguments[0] as MemberExpression;
                    string           newAlias = GenerateAliasForMember(alias, member);

                    Tenor.Data.ConditionCollection newCc = new Tenor.Data.ConditionCollection();
                    ReadWhereExpressions(newCc, mce.Arguments[1], not, newAlias);
                    if (cc.Count > 0 && cc[cc.Count - 1].GetType() != typeof(Tenor.Data.LogicalOperator))
                    {
                        cc.Add(Tenor.Data.LogicalOperator.And);
                    }
                    cc.Add(newCc);
                }
                break;

                default:
                    throw new NotImplementedException("Linq method call to '" + mce.Method.Name + "' is not implemented. Please, send a feature request.");
                }
            }
            break;

            default:
                throw new NotImplementedException("Linq '" + ex.NodeType.ToString() + "' is not implemented. Please, send a feature request.");
            }
        }