예제 #1
0
        static void EnsureTrimCharArgumentIsSpaces(DbExpression exp)
        {
            var m = exp as DbMemberExpression;

            if (m == null)
            {
                throw new NotSupportedException();
            }

            DbParameterExpression p;

            if (!DbExpressionExtension.TryConvertToParameterExpression(m, out p))
            {
                throw new NotSupportedException();
            }

            var arg = p.Value;

            if (arg == null)
            {
                throw new NotSupportedException();
            }

            var chars = arg as char[];

            if (chars.Length != 1 || chars[0] != ' ')
            {
                throw new NotSupportedException();
            }
        }
예제 #2
0
        public void Process(DbMethodCallExpression exp, SqlGenerator generator)
        {
            DbExpression left  = exp.Arguments[0];
            DbExpression right = exp.Arguments[1];

            left  = DbExpressionExtension.StripInvalidConvert(left);
            right = DbExpressionExtension.StripInvalidConvert(right);

            //明确 left right 其中一边一定为 null
            if (DbExpressionExtension.AffirmExpressionRetValueIsNull(right))
            {
                left.Accept(generator);
                generator.SqlBuilder.Append(" IS NOT NULL");
                return;
            }

            if (DbExpressionExtension.AffirmExpressionRetValueIsNull(left))
            {
                right.Accept(generator);
                generator.SqlBuilder.Append(" IS NOT NULL");
                return;
            }

            SqlGenerator.AmendDbInfo(left, right);

            left.Accept(generator);
            generator.SqlBuilder.Append(" <> ");
            right.Accept(generator);
        }
예제 #3
0
        public override DbExpression Visit(DbEqualExpression exp)
        {
            DbExpression left  = exp.Left;
            DbExpression right = exp.Right;

            left  = DbExpressionHelper.OptimizeDbExpression(left);
            right = DbExpressionHelper.OptimizeDbExpression(right);

            //明确 left right 其中一边一定为 null
            if (DbExpressionExtension.AffirmExpressionRetValueIsNull(right))
            {
                left.Accept(this);
                this._sqlBuilder.Append(" IS NULL");
                return(exp);
            }

            if (DbExpressionExtension.AffirmExpressionRetValueIsNull(left))
            {
                right.Accept(this);
                this._sqlBuilder.Append(" IS NULL");
                return(exp);
            }

            AmendDbInfo(left, right);

            left.Accept(this);
            this._sqlBuilder.Append(" = ");
            right.Accept(this);

            return(exp);
        }
예제 #4
0
        static void Method_Sql_Equals(DbMethodCallExpression exp, SqlGenerator generator)
        {
            DbExpression left  = exp.Arguments[0];
            DbExpression right = exp.Arguments[1];

            left  = DbExpressionExtension.StripInvalidConvert(left);
            right = DbExpressionExtension.StripInvalidConvert(right);

            //明确 left right 其中一边一定为 null
            if (DbExpressionHelper.AffirmExpressionRetValueIsNullOrEmpty(right))
            {
                left.Accept(generator);
                generator.SqlBuilder.Append(" IS NULL");
                return;
            }

            if (DbExpressionHelper.AffirmExpressionRetValueIsNullOrEmpty(left))
            {
                right.Accept(generator);
                generator.SqlBuilder.Append(" IS NULL");
                return;
            }

            SqlGenerator.AmendDbInfo(left, right);

            left.Accept(generator);
            generator.SqlBuilder.Append(" = ");
            right.Accept(generator);
        }
예제 #5
0
        static void Method_Sql_Equals(DbMethodCallExpression exp, SqlGenerator generator)
        {
            DbExpression left  = exp.Arguments[0];
            DbExpression right = exp.Arguments[1];

            left  = DbExpressionHelper.OptimizeDbExpression(left);
            right = DbExpressionHelper.OptimizeDbExpression(right);

            //明确 left right 其中一边一定为 null
            if (DbExpressionExtension.AffirmExpressionRetValueIsNull(right))
            {
                left.Accept(generator);
                generator._sqlBuilder.Append(" IS NULL");
                return;
            }

            if (DbExpressionExtension.AffirmExpressionRetValueIsNull(left))
            {
                right.Accept(generator);
                generator._sqlBuilder.Append(" IS NULL");
                return;
            }

            AmendDbInfo(left, right);

            left.Accept(generator);
            generator._sqlBuilder.Append(" = ");
            right.Accept(generator);

            return;
        }
예제 #6
0
        /// <summary>
        /// 尝试将 exp 转换成 DbParameterExpression。
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public static DbExpression OptimizeDbExpression(this DbExpression exp)
        {
            DbExpression stripedExp = DbExpressionExtension.StripInvalidConvert(exp);

            DbExpression tempExp = stripedExp;

            List <DbConvertExpression> cList = null;

            while (tempExp.NodeType == DbExpressionType.Convert)
            {
                if (cList == null)
                {
                    cList = new List <DbConvertExpression>();
                }

                DbConvertExpression c = (DbConvertExpression)tempExp;
                cList.Add(c);
                tempExp = c.Operand;
            }

            if (tempExp.NodeType == DbExpressionType.Constant || tempExp.NodeType == DbExpressionType.Parameter)
            {
                return(stripedExp);
            }

            if (tempExp.NodeType == DbExpressionType.MemberAccess)
            {
                DbMemberExpression dbMemberExp = (DbMemberExpression)tempExp;

                if (ExistDateTime_NowOrDateTime_UtcNow(dbMemberExp))
                {
                    return(stripedExp);
                }

                DbParameterExpression val;
                if (DbExpressionExtension.TryConvertToParameterExpression(dbMemberExp, out val))
                {
                    if (cList != null)
                    {
                        if (val.Value == DBNull.Value)//如果是 null,则不需要 Convert 了,在数据库里没意义
                        {
                            return(val);
                        }

                        DbConvertExpression c = null;
                        for (int i = cList.Count - 1; i > -1; i--)
                        {
                            DbConvertExpression item = cList[i];
                            c = new DbConvertExpression(item.Type, val);
                        }

                        return(c);
                    }

                    return(val);
                }
            }

            return(stripedExp);
        }
예제 #7
0
        public override DbExpression Visit(DbMemberExpression exp)
        {
            MemberInfo member = exp.Member;

            if (member.DeclaringType == UtilConstants.TypeOfDateTime)
            {
                if (member == UtilConstants.PropertyInfo_DateTime_Now)
                {
                    this._sqlBuilder.Append("GETDATE()");
                    return(exp);
                }

                if (member == UtilConstants.PropertyInfo_DateTime_UtcNow)
                {
                    this._sqlBuilder.Append("GETUTCDATE()");
                    return(exp);
                }

                if (member == UtilConstants.PropertyInfo_DateTime_Today)
                {
                    this.BuildCastState("GETDATE()", "DATE");
                    return(exp);
                }

                if (member == UtilConstants.PropertyInfo_DateTime_Date)
                {
                    this.BuildCastState(exp.Expression, "DATE");
                    return(exp);
                }

                if (this.IsDatePart(exp))
                {
                    return(exp);
                }
            }


            DbParameterExpression newExp;

            if (DbExpressionExtension.TryConvertToParameterExpression(exp, out newExp))
            {
                return(newExp.Accept(this));
            }

            if (member.Name == "Length" && member.DeclaringType == UtilConstants.TypeOfString)
            {
                this._sqlBuilder.Append("LEN(");
                exp.Expression.Accept(this);
                this._sqlBuilder.Append(")");

                return(exp);
            }
            else if (member.Name == "Value" && ReflectionExtension.IsNullable(exp.Expression.Type))
            {
                exp.Expression.Accept(this);
                return(exp);
            }

            throw new NotSupportedException(string.Format("'{0}.{1}' is not supported.", member.DeclaringType.FullName, member.Name));
        }
예제 #8
0
        public override DbExpression Visit(DbUpdateExpression exp)
        {
            this._sqlBuilder.Append("UPDATE ");
            this.AppendTable(exp.Table);
            this._sqlBuilder.Append(" SET ");

            bool first = true;

            foreach (var item in exp.UpdateColumns)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    this._sqlBuilder.Append(",");
                }

                this.QuoteName(item.Key.Name);
                this._sqlBuilder.Append("=");

                DbExpression valExp = DbExpressionExtension.StripInvalidConvert(item.Value);
                AmendDbInfo(item.Key, valExp);
                valExp.Accept(this.ValueExpressionVisitor);
            }

            this.BuildWhereState(exp.Condition);

            return(exp);
        }
예제 #9
0
        public override DbExpression Visit(DbConvertExpression exp)
        {
            DbExpression stripedExp = DbExpressionExtension.StripInvalidConvert(exp);

            if (stripedExp.NodeType != DbExpressionType.Convert)
            {
                stripedExp.Accept(this);
                return(exp);
            }

            exp = (DbConvertExpression)stripedExp;

            string dbTypeString;

            if (TryGetCastTargetDbTypeString(exp.Operand.Type, exp.Type, out dbTypeString, false))
            {
                this.BuildCastState(exp.Operand, dbTypeString);
            }
            else
            {
                exp.Operand.Accept(this);
            }

            return(exp);
        }
        static void Method_Contains(DbMethodCallExpression exp, SqlGenerator generator)
        {
            MethodInfo method = exp.Method;

            if (method.DeclaringType == UtilConstants.TypeOfString)
            {
                Method_String_Contains(exp, generator);
                return;
            }

            List <DbExpression> exps    = new List <DbExpression>();
            IEnumerable         values  = null;
            DbExpression        operand = null;

            Type declaringType = method.DeclaringType;

            if (typeof(IList).IsAssignableFrom(declaringType) || (declaringType.IsGenericType() && typeof(ICollection <>).MakeGenericType(declaringType.GetGenericArguments()).IsAssignableFrom(declaringType)))
            {
                DbMemberExpression memberExp = exp.Object as DbMemberExpression;

                if (memberExp == null || !memberExp.IsEvaluable())
                {
                    throw new NotSupportedException(exp.ToString());
                }

                values  = DbExpressionExtension.Evaluate(memberExp) as IEnumerable; //Enumerable
                operand = exp.Arguments[0];
                goto constructInState;
            }
            if (method.IsStatic && declaringType == typeof(Enumerable) && exp.Arguments.Count == 2)
            {
                DbMemberExpression memberExp = exp.Arguments[0] as DbMemberExpression;

                if (memberExp == null || !memberExp.IsEvaluable())
                {
                    throw new NotSupportedException(exp.ToString());
                }

                values  = DbExpressionExtension.Evaluate(memberExp) as IEnumerable;
                operand = exp.Arguments[1];
                goto constructInState;
            }

            throw UtilExceptions.NotSupportedMethod(exp.Method);

constructInState:
            foreach (object value in values)
            {
                if (value == null)
                {
                    exps.Add(DbExpression.Constant(null, operand.Type));
                }
                else
                {
                    exps.Add(DbExpression.Parameter(value));
                }
            }
            In(generator, exps, operand);
        }
예제 #11
0
        public override DbExpression Visit(DbEqualExpression exp)
        {
            DbExpression left  = exp.Left;
            DbExpression right = exp.Right;

            left  = DbExpressionExtension.StripInvalidConvert(left);
            right = DbExpressionExtension.StripInvalidConvert(right);

            MethodInfo method_Sql_Equals = PublicConstants.MethodInfo_Sql_Equals.MakeGenericMethod(left.Type);

            /* Sql.Equals(left, right) */
            DbMethodCallExpression left_equals_right = DbExpression.MethodCall(null, method_Sql_Equals, new List <DbExpression>(2)
            {
                left, right
            });

            if (right.NodeType == DbExpressionType.Parameter || right.NodeType == DbExpressionType.Constant || left.NodeType == DbExpressionType.Parameter || left.NodeType == DbExpressionType.Constant || right.NodeType == DbExpressionType.SubQuery || left.NodeType == DbExpressionType.SubQuery || !left.Type.CanNull() || !right.Type.CanNull())
            {
                /*
                 * a.Name == name --> a.Name == name
                 * a.Id == (select top 1 T.Id from T) --> a.Id == (select top 1 T.Id from T)
                 * 对于上述查询,我们不考虑 null
                 */

                left_equals_right.Accept(this);
                return(exp);
            }


            /*
             * a.Name == a.XName --> a.Name == a.XName or (a.Name is null and a.XName is null)
             */

            /* Sql.Equals(left, null) */
            var left_is_null = DbExpression.MethodCall(null, method_Sql_Equals, new List <DbExpression>(2)
            {
                left, DbExpression.Constant(null, left.Type)
            });

            /* Sql.Equals(right, null) */
            var right_is_null = DbExpression.MethodCall(null, method_Sql_Equals, new List <DbExpression>(2)
            {
                right, DbExpression.Constant(null, right.Type)
            });

            /* Sql.Equals(left, null) && Sql.Equals(right, null) */
            var left_is_null_and_right_is_null = DbExpression.And(left_is_null, right_is_null);

            /* Sql.Equals(left, right) || (Sql.Equals(left, null) && Sql.Equals(right, null)) */
            var left_equals_right_or_left_is_null_and_right_is_null = DbExpression.Or(left_equals_right, left_is_null_and_right_is_null);

            left_equals_right_or_left_is_null_and_right_is_null.Accept(this);

            return(exp);
        }
예제 #12
0
        public override DbExpression Visit(DbInsertExpression exp)
        {
            string separator = "";

            this._sqlBuilder.Append("INSERT INTO ");
            this.AppendTable(exp.Table);
            this._sqlBuilder.Append("(");

            separator = "";
            foreach (var item in exp.InsertColumns)
            {
                this._sqlBuilder.Append(separator);
                this.QuoteName(item.Key.Name);
                separator = ",";
            }

            this._sqlBuilder.Append(")");

            if (exp.Returns.Count > 0)
            {
                this._sqlBuilder.Append(" output ");
                separator = "";
                foreach (DbColumn returnColumn in exp.Returns)
                {
                    this._sqlBuilder.Append(separator);
                    this._sqlBuilder.Append("inserted.");
                    this.QuoteName(returnColumn.Name);
                    separator = ",";
                }
            }

            this._sqlBuilder.Append(" VALUES(");
            separator = "";
            foreach (var item in exp.InsertColumns)
            {
                this._sqlBuilder.Append(separator);

                DbExpression valExp = DbExpressionExtension.StripInvalidConvert(item.Value);
                AmendDbInfo(item.Key, valExp);
                valExp.Accept(this.ValueExpressionVisitor);
                separator = ",";
            }

            this._sqlBuilder.Append(")");

            return(exp);
        }
예제 #13
0
        /// <summary>
        /// 判定 exp 返回值肯定是 null 或 ''
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public static bool AffirmExpressionRetValueIsNullOrEmpty(this DbExpression exp)
        {
            exp = DbExpressionExtension.StripConvert(exp);

            if (exp.NodeType == DbExpressionType.Constant)
            {
                var c = (DbConstantExpression)exp;
                return(IsNullOrEmpty(c.Value));
            }

            if (exp.NodeType == DbExpressionType.Parameter)
            {
                var p = (DbParameterExpression)exp;
                return(IsNullOrEmpty(p.Value));
            }

            return(false);
        }
예제 #14
0
        public override DbExpression Visit(DbConvertExpression exp)
        {
            DbExpression stripedExp = DbExpressionExtension.StripInvalidConvert(exp);

            if (stripedExp.NodeType != DbExpressionType.Convert)
            {
                EnsureDbExpressionReturnCSharpBoolean(stripedExp).Accept(this);
                return(exp);
            }

            exp = (DbConvertExpression)stripedExp;

            if (exp.Type == PublicConstants.TypeOfString)
            {
                this.SqlBuilder.Append("TO_CHAR(");
                exp.Operand.Accept(this);
                this.SqlBuilder.Append(")");
                return(exp);
            }

            if (exp.Type == PublicConstants.TypeOfDateTime)
            {
                this.SqlBuilder.Append("TO_TIMESTAMP(");
                exp.Operand.Accept(this);
                this.SqlBuilder.Append(",'yyyy-mm-dd hh24:mi:ssxff')");
                return(exp);
            }

            string dbTypeString;

            if (TryGetCastTargetDbTypeString(exp.Operand.Type, exp.Type, out dbTypeString, false))
            {
                this.BuildCastState(EnsureDbExpressionReturnCSharpBoolean(exp.Operand), dbTypeString);
            }
            else
            {
                EnsureDbExpressionReturnCSharpBoolean(exp.Operand).Accept(this);
            }

            return(exp);
        }
예제 #15
0
        static void Method_NotEquals(DbMethodCallExpression exp, SqlGenerator generator)
        {
            MethodInfo method = exp.Method;

            if (method.DeclaringType != UtilConstants.TypeOfSql)
            {
                throw UtilExceptions.NotSupportedMethod(method);
            }

            DbExpression left  = exp.Arguments[0];
            DbExpression right = exp.Arguments[1];

            left  = DbExpressionHelper.OptimizeDbExpression(left);
            right = DbExpressionHelper.OptimizeDbExpression(right);

            //明确 left right 其中一边一定为 null
            if (DbExpressionExtension.AffirmExpressionRetValueIsNull(right))
            {
                left.Accept(generator);
                generator._sqlBuilder.Append(" IS NOT NULL");
                return;
            }

            if (DbExpressionExtension.AffirmExpressionRetValueIsNull(left))
            {
                right.Accept(generator);
                generator._sqlBuilder.Append(" IS NOT NULL");
                return;
            }

            AmendDbInfo(left, right);

            left.Accept(generator);
            generator._sqlBuilder.Append(" <> ");
            right.Accept(generator);

            return;
        }
예제 #16
0
        public override DbExpression Visit(DbInsertExpression exp)
        {
            string separator = "";

            this._sqlBuilder.Append("INSERT INTO ");
            this.AppendTable(exp.Table);
            this._sqlBuilder.Append("(");

            separator = "";
            foreach (var item in exp.InsertColumns)
            {
                this._sqlBuilder.Append(separator);
                this.QuoteName(item.Key.Name);
                separator = ",";
            }

            this._sqlBuilder.Append(")");

            this.AppendOutputClause(exp.Returns);

            this._sqlBuilder.Append(" VALUES(");
            separator = "";
            foreach (var item in exp.InsertColumns)
            {
                this._sqlBuilder.Append(separator);

                DbExpression valExp = DbExpressionExtension.StripInvalidConvert(item.Value);
                AmendDbInfo(item.Key, valExp);
                DbValueExpressionTransformer.Transform(valExp).Accept(this);
                separator = ",";
            }

            this._sqlBuilder.Append(")");

            return(exp);
        }
예제 #17
0
        public override DbExpression Visit(DbConvertExpression exp)
        {
            DbExpression stripedExp = DbExpressionExtension.StripInvalidConvert(exp);

            if (stripedExp.NodeType != DbExpressionType.Convert)
            {
                stripedExp.Accept(this);
                return(exp);
            }

            exp = (DbConvertExpression)stripedExp;

            string dbTypeString;

            if (TryGetCastTargetDbTypeString(exp.Operand.Type, exp.Type, out dbTypeString, false))
            {
                this.BuildCastState(exp.Operand, dbTypeString);
            }
            else
            {
                Type targetType = ReflectionExtension.GetUnderlyingType(exp.Type);
                if (targetType == PublicConstants.TypeOfDateTime)
                {
                    /* DATETIME('2016-08-06 09:01:24') */
                    this.SqlBuilder.Append("DATETIME(");
                    exp.Operand.Accept(this);
                    this.SqlBuilder.Append(")");
                }
                else
                {
                    exp.Operand.Accept(this);
                }
            }

            return(exp);
        }
예제 #18
0
        public override DbExpression Visit(DbMemberExpression exp)
        {
            MemberInfo member = exp.Member;

            if (member == OracleSemantics.PropertyInfo_ROWNUM)
            {
                this.SqlBuilder.Append("ROWNUM");
                return(exp);
            }

            if (member.DeclaringType == PublicConstants.TypeOfDateTime)
            {
                if (member == PublicConstants.PropertyInfo_DateTime_Now)
                {
                    this.SqlBuilder.Append("SYSTIMESTAMP");
                    return(exp);
                }

                if (member == PublicConstants.PropertyInfo_DateTime_UtcNow)
                {
                    this.SqlBuilder.Append("SYS_EXTRACT_UTC(SYSTIMESTAMP)");
                    return(exp);
                }

                if (member == PublicConstants.PropertyInfo_DateTime_Today)
                {
                    //other way: this.SqlBuilder.Append("TO_DATE(TO_CHAR(SYSDATE,'yyyy-mm-dd'),'yyyy-mm-dd')");
                    this.SqlBuilder.Append("TRUNC(SYSDATE,'DD')");
                    return(exp);
                }

                if (member == PublicConstants.PropertyInfo_DateTime_Date)
                {
                    this.SqlBuilder.Append("TRUNC(");
                    exp.Expression.Accept(this);
                    this.SqlBuilder.Append(",'DD')");
                    return(exp);
                }

                if (this.IsDatePart(exp))
                {
                    return(exp);
                }
            }

            if (this.IsDateSubtract(exp))
            {
                return(exp);
            }

            if (member.Name == "Length" && member.DeclaringType == PublicConstants.TypeOfString)
            {
                this.SqlBuilder.Append("LENGTH(");
                exp.Expression.Accept(this);
                this.SqlBuilder.Append(")");

                return(exp);
            }

            if (member.Name == "Value" && ReflectionExtension.IsNullable(exp.Expression.Type))
            {
                exp.Expression.Accept(this);
                return(exp);
            }

            DbParameterExpression newExp;

            if (DbExpressionExtension.TryConvertToParameterExpression(exp, out newExp))
            {
                return(newExp.Accept(this));
            }

            throw new NotSupportedException(string.Format("'{0}.{1}' is not supported.", member.DeclaringType.FullName, member.Name));
        }
예제 #19
0
        public override DbExpression Visit(DbNotEqualExpression exp)
        {
            DbExpression left  = exp.Left;
            DbExpression right = exp.Right;

            left  = DbExpressionExtension.StripInvalidConvert(left);
            right = DbExpressionExtension.StripInvalidConvert(right);

            MethodInfo method_Sql_NotEquals = UtilConstants.MethodInfo_Sql_NotEquals.MakeGenericMethod(left.Type);

            /* Sql.NotEquals(left, right) */
            DbMethodCallExpression left_not_equals_right = DbExpression.MethodCall(null, method_Sql_NotEquals, new List <DbExpression>(2)
            {
                left, right
            });

            //明确 left right 其中一边一定为 null
            if (DbExpressionExtension.AffirmExpressionRetValueIsNull(right) || DbExpressionExtension.AffirmExpressionRetValueIsNull(left))
            {
                /*
                 * a.Name != null --> a.Name != null
                 */

                left_not_equals_right.Accept(this);
                return(exp);
            }

            if (right.NodeType == DbExpressionType.SubQuery || left.NodeType == DbExpressionType.SubQuery)
            {
                /*
                 * a.Id != (select top 1 T.Id from T) --> a.Id <> (select top 1 T.Id from T),对于这种查询,我们不考虑 null
                 */

                left_not_equals_right.Accept(this);
                return(exp);
            }

            MethodInfo method_Sql_Equals = UtilConstants.MethodInfo_Sql_Equals.MakeGenericMethod(left.Type);

            if (left.NodeType == DbExpressionType.Parameter || left.NodeType == DbExpressionType.Constant)
            {
                var t = right;
                right = left;
                left  = t;
            }
            if (right.NodeType == DbExpressionType.Parameter || right.NodeType == DbExpressionType.Constant)
            {
                /*
                 * 走到这说明 name 不可能为 null
                 * a.Name != name --> a.Name <> name or a.Name is null
                 */

                if (left.NodeType != DbExpressionType.Parameter && left.NodeType != DbExpressionType.Constant)
                {
                    /*
                     * a.Name != name --> a.Name <> name or a.Name is null
                     */

                    /* Sql.Equals(left, null) */
                    var left_is_null1 = DbExpression.MethodCall(null, method_Sql_Equals, new List <DbExpression>(2)
                    {
                        left, DbExpression.Constant(null, left.Type)
                    });

                    /* Sql.NotEquals(left, right) || Sql.Equals(left, null) */
                    var left_not_equals_right_or_left_is_null = DbExpression.Or(left_not_equals_right, left_is_null1);
                    left_not_equals_right_or_left_is_null.Accept(this);
                }
                else
                {
                    /*
                     * name != name1 --> name <> name,其中 name 和 name1 都为变量且都不可能为 null
                     */

                    left_not_equals_right.Accept(this);
                }

                return(exp);
            }


            /*
             * a.Name != a.XName --> a.Name <> a.XName or (a.Name is null and a.XName is not null) or (a.Name is not null and a.XName is null)
             * ## a.Name != a.XName 不能翻译成:not (a.Name == a.XName or (a.Name is null and a.XName is null)),因为数据库里的 not 有时候并非真正意义上的“取反”!
             * 当 a.Name 或者 a.XName 其中一个字段有为 NULL,另一个字段有值时,会查不出此条数据 ##
             */

            DbConstantExpression null_Constant = DbExpression.Constant(null, left.Type);

            /* Sql.Equals(left, null) */
            var left_is_null = DbExpression.MethodCall(null, method_Sql_Equals, new List <DbExpression>(2)
            {
                left, null_Constant
            });
            /* Sql.NotEquals(left, null) */
            var left_is_not_null = DbExpression.MethodCall(null, method_Sql_NotEquals, new List <DbExpression>(2)
            {
                left, null_Constant
            });

            /* Sql.Equals(right, null) */
            var right_is_null = DbExpression.MethodCall(null, method_Sql_Equals, new List <DbExpression>(2)
            {
                right, null_Constant
            });
            /* Sql.NotEquals(right, null) */
            var right_is_not_null = DbExpression.MethodCall(null, method_Sql_NotEquals, new List <DbExpression>(2)
            {
                right, null_Constant
            });

            /* Sql.Equals(left, null) && Sql.NotEquals(right, null) */
            var left_is_null_and_right_is_not_null = DbExpression.And(left_is_null, right_is_not_null);

            /* Sql.NotEquals(left, null) && Sql.Equals(right, null) */
            var left_is_not_null_and_right_is_null = DbExpression.And(left_is_not_null, right_is_null);

            /* (Sql.Equals(left, null) && Sql.NotEquals(right, null)) || (Sql.NotEquals(left, null) && Sql.Equals(right, null)) */
            var left_is_null_and_right_is_not_null_or_left_is_not_null_and_right_is_null = DbExpression.Or(left_is_null_and_right_is_not_null, left_is_not_null_and_right_is_null);

            /* Sql.NotEquals(left, right) || (Sql.Equals(left, null) && Sql.NotEquals(right, null)) || (Sql.NotEquals(left, null) && Sql.Equals(right, null)) */
            var e = DbExpression.Or(left_not_equals_right, left_is_null_and_right_is_not_null_or_left_is_not_null_and_right_is_null);

            e.Accept(this);

            return(exp);
        }
예제 #20
0
        public void Process(DbMethodCallExpression exp, SqlGeneratorBase generator)
        {
            MethodInfo method = exp.Method;

            if (exp.Method == PublicConstants.MethodInfo_String_Contains)
            {
                Method_String_Contains(exp, generator);
                return;
            }

            List <DbExpression> exps    = new List <DbExpression>();
            IEnumerable         values  = null;
            DbExpression        operand = null;

            Type declaringType = method.DeclaringType;

            if (typeof(IList).IsAssignableFrom(declaringType) || (declaringType.IsGenericType && typeof(ICollection <>).MakeGenericType(declaringType.GetGenericArguments()).IsAssignableFrom(declaringType)))
            {
                if (exp.Object.NodeType == DbExpressionType.SqlQuery)
                {
                    /* where Id in(select id from T) */

                    operand = exp.Arguments[0];
                    In(generator, (DbSqlQueryExpression)exp.Object, operand);
                    return;
                }

                if (!exp.Object.IsEvaluable())
                {
                    throw new NotSupportedException(exp.ToString());
                }

                values  = DbExpressionExtension.Evaluate(exp.Object) as IEnumerable; //Enumerable
                operand = exp.Arguments[0];
                goto constructInState;
            }
            if (method.IsStatic && declaringType == typeof(Enumerable) && exp.Arguments.Count == 2)
            {
                DbExpression arg0 = exp.Arguments[0];
                if (arg0.NodeType == DbExpressionType.SqlQuery)
                {
                    /* where Id in(select id from T) */

                    operand = exp.Arguments[1];
                    In(generator, (DbSqlQueryExpression)arg0, operand);
                    return;
                }

                if (!arg0.IsEvaluable())
                {
                    throw UtilExceptions.NotSupportedMethod(exp.Method);
                }

                values  = DbExpressionExtension.Evaluate(arg0) as IEnumerable;
                operand = exp.Arguments[1];
                goto constructInState;
            }

            throw UtilExceptions.NotSupportedMethod(exp.Method);

constructInState:
            foreach (object value in values)
            {
                if (value == null)
                {
                    exps.Add(DbExpression.Constant(null, operand.Type));
                }
                else
                {
                    Type valueType = value.GetType();
                    if (valueType.IsEnum)
                    {
                        valueType = Enum.GetUnderlyingType(valueType);
                    }

                    if (Utils.IsToStringableNumericType(valueType))
                    {
                        exps.Add(DbExpression.Constant(value));
                    }
                    else
                    {
                        exps.Add(DbExpression.Parameter(value));
                    }
                }
            }

            In(generator, exps, operand);
        }