internal static CqtExpression ConcatArgs(ExpressionConverter parent, Expression linq, Expression[] linqArgs)
            {
                var args = linqArgs
                        .Where(arg => !arg.IsNullConstant()) // remove null constants   
                        .Select(arg => ConvertToString(parent, arg)) // Apply ToString semantics                    
                        .ToArray();

                //if all args was null constants, optimize the entire expression to constant "" 
                // e.g null + null + null == ""
                if (args.Length == 0)
                {
                    return DbExpressionBuilder.Constant(string.Empty);
                }

                var current = args.First();
                foreach (var next in args.Skip(1)) //concat all args
                {
                    current = parent.CreateCanonicalFunction(Concat, linq, current, next);
                }

                return current;
            }
 internal static CqtExpression ConcatArgs(ExpressionConverter parent, BinaryExpression linq)
 {
     return ConcatArgs(parent, linq, GetConcatArgs(linq).ToArray());
 }
            internal static DbExpression ConvertToString(ExpressionConverter parent,  LinqExpression linqExpression)
            {
                if (linqExpression.Type == typeof(object))
                {
                    var constantExpression = linqExpression as ConstantExpression;
                    linqExpression =
                        constantExpression != null ?
                            Expression.Constant(constantExpression.Value) :
                            linqExpression.RemoveConvert();
                }

                var expression = parent.TranslateExpression(linqExpression);
                var clrType = TypeSystem.GetNonNullableType(linqExpression.Type);

                if (clrType.IsEnum)
                {
                    //Flag enums are not supported.
                    if (Attribute.IsDefined(clrType, typeof(FlagsAttribute)))
                    {
                        throw new NotSupportedException(Strings.Elinq_ToStringNotSupportedForEnumsWithFlags);
                    }

                    if (linqExpression.IsNullConstant())
                    {
                        return DbExpressionBuilder.Constant(string.Empty);
                    }

                    //Constant expression, optimize to constant name
                    if (linqExpression.NodeType == ExpressionType.Constant)
                    {
                        var value = ((ConstantExpression)linqExpression).Value;
                        var name = Enum.GetName(clrType, value) ?? value.ToString();
                        return DbExpressionBuilder.Constant(name);
                    }

                    var integralType = clrType.GetEnumUnderlyingType();
                    var type = parent.GetValueLayerType(integralType);

                    var values = clrType.GetEnumValues()
                        .Cast<object>()
                        .Select(v => System.Convert.ChangeType(v, integralType, CultureInfo.InvariantCulture)) //cast to integral type so that unmapped enum types works too
                        .Select(v => DbExpressionBuilder.Constant(v))
                        .Select(c => (DbExpression)expression.CastTo(type).Equal(c)) //cast expression to integral type before comparing to constant
                        .Concat(new[] { expression.CastTo(type).IsNull() }); // default case
                        
                    var names = clrType.GetEnumNames()
                        .Select(s => DbExpressionBuilder.Constant(s))
                        .Concat(new[] { DbExpressionBuilder.Constant(string.Empty) }); // default case

                    //translate unnamed enum values for the else clause, raw linq -> as integral value -> translate to cqt -> to string
                    //e.g.  ((DayOfWeek)99) -> "99"
                    var asIntegralLinq = LinqExpression.Convert(linqExpression, integralType);
                    var asStringCqt = parent
                        .TranslateExpression(asIntegralLinq)
                        .CastTo(parent.GetValueLayerType(typeof(string)));

                    return DbExpressionBuilder.Case(values, names, asStringCqt);
                }
                else if (TypeSemantics.IsPrimitiveType(expression.ResultType, PrimitiveTypeKind.String))
                {
                    return StripNull(linqExpression, expression, expression);
                }
                else if (TypeSemantics.IsPrimitiveType(expression.ResultType, PrimitiveTypeKind.Guid))
                {
                    return StripNull(linqExpression, expression, expression.CastTo(parent.GetValueLayerType(typeof(string))).ToLower());
                }
                else if (TypeSemantics.IsPrimitiveType(expression.ResultType, PrimitiveTypeKind.Boolean))
                {
                    if (linqExpression.IsNullConstant())
                    {
                        return DbExpressionBuilder.Constant(string.Empty);
                    }

                    if (linqExpression.NodeType == ExpressionType.Constant)
                    {
                        var name = ((ConstantExpression)linqExpression).Value.ToString();
                        return DbExpressionBuilder.Constant(name);
                    }

                    var whenTrue = expression.Equal(DbExpressionBuilder.True);
                    var whenFalse = expression.Equal(DbExpressionBuilder.False);
                    var thenTrue = DbExpressionBuilder.Constant(true.ToString());
                    var thenFalse = DbExpressionBuilder.Constant(false.ToString());

                    return DbExpressionBuilder.Case(
                        new[] { whenTrue, whenFalse },
                        new[] { thenTrue, thenFalse },
                        DbExpressionBuilder.Constant(string.Empty));
                }
                else
                {
                    if (!SupportsCastToString(expression.ResultType))
                    {
                        throw new NotSupportedException(
                            Strings.Elinq_ToStringNotSupportedForType(expression.ResultType.EdmType.Name));
                    }

                    //treat all other types as a simple cast
                    return StripNull(linqExpression, expression, expression.CastTo(parent.GetValueLayerType(typeof(string))));
                }
            }